在我们的程序中,经常会有一些耗时较长的运算,为了保证用户体验,不引起界面不响应,我们一般会采用多线程操作,让耗时操作在后台完成,完成后再进行处理或给出提示,在运行中,也会时时去刷新界面上的进度条等显示元,必要进,还要控制后台线程中断当前操作。

以前,类似的应用会比较麻烦,需要写的代码较多,也很容易出现异常。在 .net中,提供了一个组件 backgroundworker就是专门解决这个问题的。

使用这个组件其实非常简单,例如,我们做一个类似如下界面的进度条的小例子,在后台线程中进行耗时运算,同时刷新界面上的滚动条和提示信息,运行结束后,弹出处理结果。

在界面上拖入backgroundWorker组件,并响应其三个事件。

代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace 多线程小例子
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

//这里就是通过响应消息,来处理界面的显示工作

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
            this.label1.Text = e.UserState.ToString();
            this.label1.Update();
        }

//这里是后台工作完成后的消息处理,可以在这里进行后续的处理工作。

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("运算终于完成了");
        }

//这里,就是后台进程开始工作时,调用工作函数的地方。你可以把你现有的处理函数写在这儿。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            work(this.backgroundWorker1);
        }

//真正的处理工作

private bool work(BackgroundWorker bk)
        {
            int tatle =10000;

for (int i = 0; i < tatle; i++)
            {
                if (bk.CancellationPending) //这里判断一下是否用户要求取消后台进行,并可以尽早退出。
                {
                    bk.ReportProgress(i, String.Format("当前值是 {0},操作被用户申请中断", i));
                    return false;
                }

//处理的过程中,通过这个函数,向主线程报告处理进度,最好是折算成百分比,与外边的进度条的最大值必须要对应。这里,我没有折算,而是把界面线程的进度条最大值调整为与这里的总数一致。
                bk.ReportProgress(i, String.Format("当前值是 {0} ", i));
            }
            return true;
        }

private void button2_Click(object sender, EventArgs e)
        {

//用户要求取消时,就这样处理一下。有时不太灵喔。

this.backgroundWorker1.CancelAsync();
        }

private void button1_Click(object sender, EventArgs e)
        {

//这一句,就是让后台工作开始。

this.backgroundWorker1.RunWorkerAsync();
        }

private void button3_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}

一般的工作,就这样的套路处理一下,基本就可以工作了,如果多个线程之间还要交互,或是有共享数据等问题,.net C# 中还是提供 System.Threading.Thread 类,跟传统用法没什么大区别,也挺好用的。具体介绍请看另一篇文章。

 
 
 
 
阅读(42298)| 评论(21)

 

 
喜欢推荐转载
 

 

 

 

 

 

 

 

 
 
关闭

玩LOFTER,免费冲印20张照片,人人有奖!     我要抢>

评论

  登录后你可以发表评论,请先登录。登录>>
2013-03-04 17:51

程序这样改就可以运行了:

public BackGroundWorkerTest()

        {
            InitializeComponent();
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
        }
for (int i = 0; i < tatle; i++)
            {
                if (bk.CancellationPending) // 判断是否用户要求取消后台进行,尽早对出
                {
                    bk.ReportProgress(i, String.Format("当前值是 {0},操作被用户申请中断", i));
                    return false;
                }
                bk.ReportProgress(i, String.Format("当前值是 {0}", i));
                Thread.Sleep(100); // 加上这一句
            }
private void button_start_Click(object sender, EventArgs e)
        {
            if (this.backgroundWorker1.IsBusy)
                return;
            this.backgroundWorker1.RunWorkerAsync();
        }
2014-03-19 09:47

mandy 回复 Wong
正解
03-17 14:05

ggajj1314 回复 Wong
 Thread.Sleep(100); // 加上这一句

加上这一句后,发现速度明显慢了不少,正常没有进度条的速度比有进度条的速度快很多。
2015-11-27 16:58

路过看到的,内容写的很好,支持~
2015-07-16 19:32

多谢博主,帮我大忙了。
2013-05-30 21:34

隐者

很不错,别的教程都太难懂,就看到你讲的很简明扼要,把总体的流程讲的很清楚。

您肯定是很有经验的程序员吧?我感觉现在C#的书要不就是逻辑上讲的不是很清晰,要不就是讲的太简单,需要的东西很多没有讲到。

很感谢。

2013-01-21 22:20

tjwangzhen
需要做如下设置,程序就可以工作了

backgroundWorker属性中的事件添加处理函数

WorkerReportsProgress属性中WorkerReportsProgress设置为true
WorkerReportsProgress属性中WorkerSupportsCancellation 设置为true     
2012-11-12 14:25

david
有点问题!
2012-10-12 20:57

有课
为什么点完之后界面就假死呢?
2012-09-25 12:31

backgroundWorker,的属性要修改一下,还有就是进度条的值要修改,取消时会有异常
2012-09-25 12:30

很给力

2012-06-20 16:17

sss

这样就能用了

除了那个“取消”不能正常使用,其他的都能用

还是很谢谢作者的,我的一个程序很慢,用了他的方法(改写),一两秒就跑完了

2012-06-20 16:14

sss

大家用的时候要在界面加入下面的东西:

一个 BackgroundWorker 一个lable 一个progressBar 还有三个button

记得 和程序中的名称 和对应的方法名 一致

2012-06-20 16:11

sss

很好

2012-06-02 10:07

9089
没法用。。。

2012-05-09 18:10

为什么我还有许多错误啊
2011-08-05 16:24

11
狗日的。浪费我的时间。什么多线程。界面卡的不行
2010-04-25 12:40

过客

开始按钮中加个这个合适一些

if (this.backgroundWorker1.IsBusy)
    {
return;
    }

2010-04-25 12:36

过客
多谢老兄!
2009-09-08 14:08

多谢!!学习啦。。。
2009-08-06 16:12

网易博友54
脑残
 
 
 
 
 
 

网易公司版权所有 ©1997-2016

 

c# BackGroundWorker 多线程操作的小例子的更多相关文章

  1. c# BackGroundWorker 多线程操作的小例子 (转)

    在我们的程序中,经常会有一些耗时较长的运算,为了保证用户体验,不引起界面不响应,我们一般会采用多线程操作,让耗时操作在后台完成,完成后再进行处理或给出提示,在运行中,也会时时去刷新界面上的进度条等显示 ...

  2. 纯C++ 连接SQL Server2005 数据库读写操作的小例子

    一个测试c++链接 sql server 数据库的例子// 数据库说明// 数据库用户为 sa , 密码为 空// 数据库为 MyDB// 表为 UserInfo// 表字段为 Name . Pass ...

  3. Linux多线程的一个小例子

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h& ...

  4. java操作xml的一个小例子

    最近两天公司事比较多,这两天自己主要跟xml打交道,今天更一下用java操作xml的一个小例子. 原来自己操作xml一直用这个包:xstream-1.4.2.jar.然后用注解的方式,很方便,自己只要 ...

  5. JS操作Cookies的小例子

    这篇文章介绍了JS操作Cookies的小例子,有需要的朋友可以参考一下. 您可能感兴趣的文章:js 保存与获取cookie的代码javascript cookie操作实例详解javascript co ...

  6. Java多线程分批发送消息的小例子

    需求: 假设有10万个用户,现在节假日做活动,需要给每个用户发送一条活动短信,为了提高程序的效率,建议使用多线程分批发送. 这里值得注意的是: 每开一个线程都会占用CPU的资源,所以线程根据所需要的条 ...

  7. JSP小例子——实现用户登录小例子(不涉及DB操作)

    实现用户登录小例子用户名和密码都为"admin",登陆成功使用服务器内部转发到login_success.jsp页面,并且提示登陆成功的用户名.如果登陆失败则请求重定向到login ...

  8. C#多线程操作界面控件的解决方案(转)

    C#中利用委托实现多线程跨线程操作 - 张小鱼 2010-10-22 08:38 在使用VS2005的时候,如果你从非创建这个控件的线程中访问这个控件或者操作这个控件的话就会抛出这个异常.这是微软为了 ...

  9. 多线程操作C++ STL vector出现概率coredump问题及尽量避免锁的双缓冲队列

    多线程操作全局变量,必须考虑同步问题,否则可能出现数据不一致, 甚至触发coredump. 前段时间, 遇到一个多线程操作了全局的vector的问题,  程序崩了.场景是这样的:某全局配置参数保存在一 ...

随机推荐

  1. eclipse 恢复SVN无法还原的文件 svn使用了还原,但本地的没有提交找回没提交代码的方法

    http://blog.sina.com.cn/s/blog_750167060102vd2n.html

  2. Cheatsheet: 2013 08.14 ~ 08.19

    .NET Lucene.Net ultra fast search for MVC or WebForms site => made easy! C# State Machines HttpCl ...

  3. 使用OmniGraffle制作原型图

    原型图设计是一个艺术创作的过程,所以我们应当使用能够提高工作效率.激发创作灵感的工具,让工具为创作服务,而不是为创作去学习如何使用工具.从这一点上说,我觉得Mac下的很多软件做的非常好,OmniGra ...

  4. IP地址验证

    /** * 验证IP地址 * * @param 待验证的字符串 * @return 如果是符合格式的字符串,返回 <b>true </b>,否则为 <b>false ...

  5. HTTP消息中header头部信息的讲解

    HTTP Request的Header信息 1.HTTP请求方式 如下表: GET 向Web服务器请求一个文件 POST 向Web服务器发送数据让Web服务器进行处理 PUT 向Web服务器发送数据并 ...

  6. Apache-Shiro+Zookeeper系统集群安全解决方案之缓存管理

    上篇[Apache-Shiro+Zookeeper系统集群安全解决方案之会话管理],解决了Shiro在系统集群开发时安全的会话共享问题,系统在使用过程中会有大量的权限检查和用户身份检验动作,为了不频繁 ...

  7. Codeforces Round #135 (Div. 2) E. Parking Lot 线段数区间合并

    E. Parking Lot time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  8. FLASH CC 2015 CANVAS (二)html中写JS调用flash中的元件、函数、变量

    注意 此贴 为个人边“开荒”边写,所以不保证就是最佳做法,也难免有错误! 正式教程会在后续开始更新 当你导出第一个canvas后,你会在保存fla的文件夹里 (每个项目默认位置)看到 如下文件,(请先 ...

  9. js addEventListener attachEvent

    attachEvent方法,为某一事件附加其它的处理事件.(不支持Mozilla系列) addEventListener方法 用于 Mozilla系列 举例: document.getElementB ...

  10. iOS - OC PList 数据存储

    前言 直接将数据写在代码里面,不是一种合理的做法.如果数据经常改,就要经常翻开对应的代码进行修改,造成代码扩展性低.因此,可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最新的数据.如 ...