多线程之BackgroundWorker组件
发布日期:2022-04-11 08:52:45 浏览次数:10 分类:博客文章

本文共 5547 字,大约阅读时间需要 18 分钟。

多线程之BackgroundWorker组件

2010-06-25  来自:新浪博客  字体大小:【  】
  • 摘要:BackgroundWorker组件在多线程编程方面使用起来非常方便,然而在开始时由于没有搞清楚它的使用机制,走了不少的弯路,现在把我在使用它的过程中的经验与诸位分享一下。

BackgroundWorker组件
在VS2005中添加了BackgroundWorker组件,该组件在多线程编程方面使用起来非常方便,然而在开始时由于没有搞清楚它的使用机制,走了不少的弯路,现在把我在使用它的过程中的经验与诸位分享一下。
 

   BackgroundWorker类中主要用到的有这列属性、方法和事件:
    重要属性:
    1、CancellationPending             获取一个值,指示应用程序是否已请求取消后台操作。通过在DoWork事件中判断CancellationPending属性可以认定是否需要取消后台操作(也就是结束线程);
    2、IsBusy                          获取一个值,指示 BackgroundWorker 是否正在运行异步操作。程序中使用IsBusy属性用来确定后台操作是否正在使用中;
    3、WorkerReportsProgress           获取或设置一个值,该值指示BackgroundWorker能否报告进度更新
    4、WorkerSupportsCancellation      获取或设置一个值,该值指示 BackgroundWorker 是否支持异步取消。设置WorkerSupportsCancellation为true使得程序可以调用CancelAsync方法提交终止挂起的后台操作的请求;
    重要方法:
    1、CancelAsync         请求取消挂起的后台操作
    2、RunWorkerAsync      开始执行后台操作
    3、ReportProgress      引发ProgressChanged事件  
    重要事件:
    1、DoWork              调用 RunWorkerAsync 时发生
    2、ProgressChanged     调用 ReportProgress 时发生
    3、RunWorkerCompleted  当后台操作已完成、被取消或引发异常时发生
    另外还有三个重要的参数是RunWorkerCompletedEventArgs以及DoWorkEventArgs、ProgressChangedEventArgs。
    BackgroundWorker的各属性、方法、事件的调用机制和顺序:
从上图可见在整个生活周期内发生了3次重要的参数传递过程:
    参数传递1:此次的参数传递是将RunWorkerAsync(Object)中的Object传递到DoWork事件的DoWorkEventArgs.Argument,由于在这里只有一个参数可以传递,所以在实际应用往封装一个类,将整个实例化的类作为RunWorkerAsync的Object传递到DoWorkEventArgs.Argument;
    参数传递2:此次是将程序运行进度传递给ProgressChanged事件,实际使用中往往使用给方法和事件更新进度条或者日志信息;
    参数传递3:在DoWork事件结束之前,将后台线程产生的结果数据赋给DoWorkEventArgs.Result一边在RunWorkerCompleted事件中调用RunWorkerCompletedEventArgs.Result属性取得后台线程产生的结果。
    另外从上图可以看到DoWork事件是在后台线程中运行的,所以在该事件中不能够操作用户界面的内容,如果需要更新用户界面,可以使用ProgressChanged事件及RunWorkCompleted事件来实现。
在WinForm中经常遇到一些费时的操作界面,比如统计某个磁盘分区的文件夹或者文件数目,如果分区很大或者文件过多的话,处理不好就会造成“假死”的情况,或者报“线程间操作无效”的异常,为了解决这个问题,可以使用委托来处理,在.net2.0中还可以用BackgroundWorker类。
BackgroundWorker类是.net 2.0里新增加的一个类,对于需要长时间操作而不需要用户长时间等待的情况可以使用这个类。
注意确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
namespace
BackgroundWorkerDemo
{
public
partial
class
MainForm : Form
{
private
BackgroundWorker worker
=
new
BackgroundWorker();
public
MainForm()
{
InitializeComponent();
worker.WorkerReportsProgress
=
true
;
worker.WorkerSupportsCancellation
=
true
;
//
正式做事情的地方
worker.DoWork
+=
new
DoWorkEventHandler(DoWork);
//
任务完称时要做的,比如提示等等
worker.ProgressChanged
+=
new
ProgressChangedEventHandler(ProgessChanged);
//
任务进行时,报告进度
worker.RunWorkerCompleted
+=
new
RunWorkerCompletedEventHandler(CompleteWork);
}
//
调用 RunWorkerAsync 时发生
public
void
DoWork(
object
sender, DoWorkEventArgs e)
{
e.Result
=
ComputeFibonacci(worker, e);
//
当ComputeFibonacci(worker, e)返回时,异步过程结束
}
//
调用 ReportProgress 时发生
public
void
ProgessChanged(
object
sender, ProgressChangedEventArgs e)
{
this
.progressBar1.Value
=
e.ProgressPercentage;
}
//
当后台操作已完成、被取消或引发异常时发生
public
void
CompleteWork(
object
sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show(
"
完成!
"
);
}
private
int
ComputeFibonacci(
object
sender, DoWorkEventArgs e)
{
for
(
int
i
=
0
; i
<
1000
; i
++
)
{
if
(worker.CancellationPending)
{
e.Cancel
=
true
;
}
else
{
worker.ReportProgress(i);
}
System.Threading.Thread.Sleep(
10
);
}
return
-
1
;
}
private
void
btnStart_Click(
object
sender, EventArgs e)
{
worker.RunWorkerAsync();
btnStart.Enabled
=
false
;
btnPause.Enabled
=
true
;
}
private
void
btnPause_Click(
object
sender, EventArgs e)
{
btnPause.Enabled
=
false
;
btnStart.Enabled
=
true
;
worker.CancelAsync();
}
}
}
 
 
假如不让调用主线程控件,则load中:
System.Windows.Forms.Form.CheckForIllegalCrossThreadCalls = false;
 
 

C#中BackgroundWorker概念详解及使用代码实现

隶属于:
主题说明
标题: C#中BackgroundWorker概念详解及使用代码实现
[创建人]
[被赞赏]0次
[被浏览]112次
[题下文章]1篇
[题下评论] 篇
最佳文章
文章列表加载中...
文章列表加载中...
作者信息读取中
...
[被赞赏]1次
[被浏览]1次
[评论] 篇
[被挑战]N次
[日期]2012-07-02 11:43
子标题: BackgroundWorker的使用
转载信息:

一个程序中需要进行大量的运算,并且需要在运算过程中支持用户一定的交互,为了获得更好的用户体验,使用BackgroundWorker来完成这一功能.

 
基本操作:
bgw.RunWorkerAsync()        :
    开始后台运行执行,
    该函数后将触发bgw.DoWorker事件,需要执行的操作写在DoWorker事件响应函数里,
    该函数也可以加参数,参数从DoWorker事件处理函数的e.Arguement里获取
 
bgw.CancelAsync()                :
    申请后台程序停止,
    注意该函数不能实际停止后台程序,只能将bgw的CancellationPending 值设为true,需要自己在后台运行的程序中判断这一值,进而停止后台程序的运行.
    注意本方法使用前,需要将bgw的WorkerSupportsCancellation 值设为true,否则将不起作用.
 
bgw.ReportProgress()        :
    在后台程序中调用,向主线程传送进度信息,
    可以带一个或两个参数,一个为INT类型的进度(0~100),一个为自定义类型的参数,可以传任意信息.
    调用后,将触发bgw.ProgressChanged事件,可以将界面变化的代码写在该事件响应函数中,之前提到的两个参数均可从bgw.ProgressChanged事件响应函数的参数e中获取,分别为e.ProgressPercentage和e.UserState.    
    注意本方法使用前,需要将bgw的WorkerReportsProgress值设为true,否则将不会触发事件.
开始后台运行:
  1. bgw= new BackgroundWorker();   
  2.           bgw.WorkerSupportsCancellation = true;  
  3.           bgw.WorkerReportsProgress = true;  
  4.   
  5.           bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);  
  6.           bgw.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);  
  7.           bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);  
  8.   
  9.           bgw.RunWorkerAsync();  
DoWork事件处理函数:
  1. void bgw_DoWork(object sender, DoWorkEventArgs e)   
  2.        {  
  3.            StartProgress();  
  4.   
  5.        }     
WorkerCompleted事件处理函数(该函数在后台处理完成后被触发)
  1. void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)   
  2.        {  
  3.            MessageBox.Show("处理完成");  
  4.        }  
ProgressChanged事件处理函数,
  1. void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)   
  2.        {  
  3.            if (e.UserState is int)  
  4.            {  
  5.                progressBar1.Value = (int)e.ProgressPercentage;  
  6.                label2.Text = e.UserState.ToString();  
  7.            }  
  8.            else if (e.UserState is List<object>)  
  9.            {  
  10.                List<object> tmp = (List<object>)e.UserState;  
  11.                progressBar1.Value = e.ProgressPercentage;  
  12.                label2.Text = tmp[0].ToString();  
  13.                this.label1.Text = tmp[1].ToString();  
  14.                this.listBox1.Items.Insert(0, tmp[2]);  
  15.            }  
  16.        }  
后台运行的代码
  1.  private void StartProgress()           
  2. {  
  3.     //do sth  
  4.   
  5.     bgw.ReportProgress(per,paraInt);  

转载地址:https://www.cnblogs.com/zhangjun1130/archive/2012/08/13/2636721.html 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:多线程之BlockingQueue中 take、offer、put、add的一些比较
下一篇:多线程之 生产者消费者模型 线程池

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月18日 11时39分40秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

C++面经总结之《Effective C++》(一) 2019-04-27
C++面经总结之《Effective C++》(二) 2019-04-27
这是什么“虎狼之词”啊!!!程序员的健康问题,看一线老中医怎么说!!! 2019-04-27
打开我的收藏夹 -- Python数据分析杂谈 2019-04-27
上手Pandas,带你玩转数据(1)-- 实例详解pandas数据结构 2019-04-27
上手Pandas,带你玩转数据(2)-- 使用pandas从多种文件中读取数据 2019-04-27
上手Pandas,带你玩转数据(3)-- pandas数据存入文件 2019-04-27
爬虫遇上不让右击、不让F12的网站,该怎么办? 2019-04-27
上手Pandas,带你玩转数据(5)-- 数据转换与数据定位 2019-04-27
上手Pandas,带你玩转数据(6)-- 摆脱对pandas可视化丑图的刻板印象吧 2019-04-27
从零开始,学会Python爬虫不再难!!! -- (2)承接:解析网页,抓取标签 丨蓄力计划 2019-04-27
linux shell — 6.初识 EXT2 文件系统 2019-04-27
Java — String(字符串) 2019-04-27
linux shell — 8.linux 磁盘与文件系统管理(2) 2019-04-27
linux — Centos 7(第一天) 使用时出现的问题及解决方法 2019-04-27
数据结构 — 查找(最基础) 2019-04-27
关于 自减运算符 (i--/--j)在 循环(for与while)中的执行过程 2019-04-27
Jquery - Jquery 包装集 2019-04-27
python - pandas 从 yahoo finance 读取 BABA 数据进行 visualization 2019-04-27
python - 【用户、商品】【购买、浏览】数据处理 2019-04-27