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

以前,类似的应用会比较麻烦,需要写的代码较多,也很容易出现异常。在 .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. 【leetcode❤python】169. Majority Element

    #Method 1import math class Solution(object):    def majorityElement(self, nums):        numsDic={}   ...

  2. APP前端公共测试点

  3. Python语言精要---下

    函数: 可以返回多个值,其实函数是返回一个对象,就是元组,元组中的元素被拆分到各个结果变量中了 匿名函数: lambda函数,仅仅由单条语句组成,结果就是返回值 这种函数没有提供名称属性 闭包: cl ...

  4. bzoj 2242: [SDOI2011]计算器 BSGS+快速幂+扩展欧几里德

    2242: [SDOI2011]计算器 Time Limit: 10 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 你被 ...

  5. Codeforces Round #281 (Div. 2) D. Vasya and Chess 水

    D. Vasya and Chess time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  6. 关于【bootstrap modal 模态框弹出瞬间消失的问题】

    前提是你没有重复引入bootstrap.js\bootstrap.min.js和modal.js.一下提供一个小例子. <button class="btnbtn-primary bt ...

  7. Spring security3入门(转)

    http://kingxss.iteye.com/blog/1908011 补充类图: 注意:1.修改为链接mysql数据库:             2.代码地址:https://github.co ...

  8. JAVA 大数据内存耗用测试

    JAVA 大数据内存耗用测试import java.lang.management.ManagementFactory;import java.lang.management.MemoryMXBean ...

  9. Java编程思想学习笔记_4(异常机制,容器)

    一.finally语句注意的细节: 当涉及到break和continue语句的时候,finally字句也会得到执行. public class Test7 { public static void m ...

  10. 【Todo】Java要学的一些比较好的框架和系统

    commons-pool apache的通用线程池 可以看看这篇文章:<使用common-pool实现的一个简单的线程池> Jmeter 性能测试 Squid Link