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

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

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

c# BackGroundWorker 多线程操作的小例子-LMLPHP

在界面上拖入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)

c# BackGroundWorker 多线程操作的小例子-LMLPHP

 
c# BackGroundWorker 多线程操作的小例子-LMLPHP

 
喜欢推荐转载
c# BackGroundWorker 多线程操作的小例子-LMLPHP
 
c# BackGroundWorker 多线程操作的小例子-LMLPHP

 
c# BackGroundWorker 多线程操作的小例子-LMLPHP

 
c# BackGroundWorker 多线程操作的小例子-LMLPHP

 
c# BackGroundWorker 多线程操作的小例子-LMLPHP

 
c# BackGroundWorker 多线程操作的小例子-LMLPHP

 
c# BackGroundWorker 多线程操作的小例子-LMLPHP

 
c# BackGroundWorker 多线程操作的小例子-LMLPHP

 
c# BackGroundWorker 多线程操作的小例子-LMLPHP

 
 
关闭

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

评论

  登录后你可以发表评论,请先登录。登录>>
c# BackGroundWorker 多线程操作的小例子-LMLPHP
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();
        }
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2014-03-19 09:47

mandy 回复 Wong
正解
c# BackGroundWorker 多线程操作的小例子-LMLPHP
03-17 14:05

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

加上这一句后,发现速度明显慢了不少,正常没有进度条的速度比有进度条的速度快很多。
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2015-11-27 16:58

路过看到的,内容写的很好,支持~
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2015-07-16 19:32

多谢博主,帮我大忙了。
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2013-05-30 21:34

隐者

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

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

很感谢。

c# BackGroundWorker 多线程操作的小例子-LMLPHP
2013-01-21 22:20

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

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

WorkerReportsProgress属性中WorkerReportsProgress设置为true
WorkerReportsProgress属性中WorkerSupportsCancellation 设置为true     
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2012-11-12 14:25

david
有点问题!
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2012-10-12 20:57

有课
为什么点完之后界面就假死呢?
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2012-09-25 12:31

backgroundWorker,的属性要修改一下,还有就是进度条的值要修改,取消时会有异常
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2012-09-25 12:30

很给力

c# BackGroundWorker 多线程操作的小例子-LMLPHP
2012-06-20 16:17

sss

这样就能用了

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

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

c# BackGroundWorker 多线程操作的小例子-LMLPHP
2012-06-20 16:14

sss

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

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

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

c# BackGroundWorker 多线程操作的小例子-LMLPHP
2012-06-20 16:11

sss

很好

c# BackGroundWorker 多线程操作的小例子-LMLPHP
2012-06-02 10:07

9089
没法用。。。

c# BackGroundWorker 多线程操作的小例子-LMLPHP
2012-05-09 18:10

为什么我还有许多错误啊
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2011-08-05 16:24

11
狗日的。浪费我的时间。什么多线程。界面卡的不行
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2010-04-25 12:40

过客

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

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

c# BackGroundWorker 多线程操作的小例子-LMLPHP
2010-04-25 12:36

过客
多谢老兄!
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2009-09-08 14:08

多谢!!学习啦。。。
c# BackGroundWorker 多线程操作的小例子-LMLPHP
2009-08-06 16:12

网易博友54
脑残
 
 
 
 
 
 

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

 
04-15 10:13