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

以前,类似的应用会比较麻烦,需要写的代码较多,也很容易出现异常。在 .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. Bootstrap_基本HTML模板

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  2. BZOJ 1513 [POI2006]Tet-Tetris 3D

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1513 题意:三维空间,有一些立方体在垂直下落.立方体的左下角坐标(x,y)以及长宽 ...

  3. jquery之event与originalEvent的关系、event事件对象用法浅析

    在jquery中,最终传入事件处理程序的 event 其实已经被 jQuery 做过标准化处理, 其原有的事件对象则被保存于 event 对象的 originalEvent 属性之中, 每个 even ...

  4. Date Picker Calendar For Oracle Forms 6i

    Giving date picker calendar option to user for date type fields in Oracle Forms. I am providing you ...

  5. Android SDK 更新镜像服务器

    搞个新的电脑,新环境下,SDK总是更新不成功.找了一下,发现有国内的镜像,记录保存一下. Android Tools Android SDK在线更新镜像服务器    中国科学院开源协会镜像站地址:   ...

  6. 异步上传图片,光用jquery不行,得用jquery.form.js插件

    异步上传图片,光用jquery不行,得用jquery.form.js插件,百度一下下载这个插件,加jquery,引入就可以了 <form id="postbackground" ...

  7. 最近用到这个强大的工具 PhysicsEditor (转)

    今天收到PhysicsEditor作者发过来的license key,所以顺便把PhysicsEditor也尝试了一下.主要是尝试将PhysicsEditor与cocos2dx,box2d结合开发的一 ...

  8. vim配置php开发环境

    1.ctags-用于代码间的跳转 安装 sudo apt-get install ctags 使用 1). 在某个目录下, 建立tags. ctags -R . --执行之后会在当前目录下生成一个ta ...

  9. 改变bootstarp图标水平方向

    我一开始是以为bootstarp已经自定义了方向的类的,但是我查阅了好久都没有看到,我这里用的是CSS3的旋转180° 1:HTML <i class="icon-thumbs-dow ...

  10. ORACLE SQL 分组

    select max(cost),suppliercode from tel_bill where period = '2014005' group by suppliercode;select * ...