线程封装组件(BackgroundWorker)和线程(Thread)
BackgroundWorker是微软的在.net Framwork中添加的一个组件,主要对线程的访问提供了一种安全的方式。简单的说就是对Thread的一次封装。
BackgroundWorker位于System.ComponentModel下,是一个继承了Component的组件,微软官方的解释为:Executes an operation on a separate thread.就是说,开始一个新的线程执行操作。

首先介绍一下BackgroundWorker的相关属性和方法:
属性:
WorkerReportsProgress:是否可以报告进度。
WorkerSupportsCancellation:是否允许异步中止。
IsBusy:是否在运行。
CancellationPending:判断BackgroundWorker是否已经异步取消。
方法:
RunWorkerAsync:开始执行任务。触发DoWork事件
ReportProgress:异步提醒,触发ProgressChanged事件,但是这个如果可以使用,必须设置WorkerReportsProgress为True
CancelAsync:取消BackgroundWorker操作。
事件:
DoWork:执行RunWorkerAsync后触发,异步执行的认为。
ProgressChanged:执行ReportProgress时触发,异步获得进度。
RunWorkerCompleted:线程结束时触发,主要有成功结束,发生异常或者取消时发生。
Thread相对来说就简单了,但是使用起来就比较麻烦了。Thread位于System.Threading的名空间下,是一个可以独立创建和操作一个线程,并且对线程进行设置优先级和获得状态的一个不可继承的类。
下面是我做的一个例子,来比较他们两个的使用。
建立一个窗体,放置了两个TextBox,分别为设置开始和结束的Progree的值,放置两个ProgressBar,分别设置为线程的Progressbar和BackGroundWorker的ProgressBar。另外放置按钮为StartBackGroundWorker,StartThread,CancelBackGroundWorker,CancelThread和PauseThread。
BackGroundWorker的使用就非常简单:
/// <summary>
/// Handles the Click event of the btnBackGroundWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void btnBackGroundWorker_Click(object sender, EventArgs e)
{
StartFrom = Convert.ToInt32(txtStart.Text);
EndTo = Convert.ToInt32(txtEnd.Text); progressBarThread.Minimum = StartFrom;
progressBarThread.Maximum = EndTo; this.btnBackGroundWorker.Enabled = false; this.backgroundWorker.RunWorkerAsync();
} /// <summary>
/// Handles the DoWork event of the backgroundWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int nValue = StartFrom; nValue <= EndTo; nValue++)
{
if (this.backgroundWorker.CancellationPending)
{
e.Cancel = true;
return;
}
this.backgroundWorker.ReportProgress(nValue);
Thread.Sleep();
}
} /// <summary>
/// Handles the ProgressChanged event of the backgroundWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param>
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.prgProcessBackGroundWorker.Value = e.ProgressPercentage;
} /// <summary>
/// Handles the RunWorkerCompleted event of the backgroundWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// 取消
if (e.Cancelled)
{
MessageBox.Show("Cancelled");
}
// 出现错误
else if (e.Error != null)
{
MessageBox.Show(e.Error.Message + Environment.NewLine + e.Error.StackTrace);
}
// 完成
else
{
MessageBox.Show("Completed");
this.btnBackGroundWorker.Enabled = true;
}
} /// <summary>
/// Handles the Click event of the btnCancelBackgroundWoker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void btnCancelBackgroundWoker_Click(object sender, EventArgs e)
{
this.backgroundWorker.CancelAsync();
}
Thread的使用就比较麻烦了,对于尤其是对异步提醒来说,需要写委托,代码量是很多,但是对于BackgroundWorker来说,却没有线程暂停和继续的方法。但是对于一般的来说,这些功能也是不用的,而且在微软的文档中还提到了,Thread的Resume和Suspend已经不推荐使用。
// 声明委托
delegate void DelegateType(int x);
DelegateType TheDelegate; // ProgressBar的开始和结束值
int StartFrom, EndTo; // 是否线程暂停
bool IsThreadPaused; ManualResetEvent CancelEvent = new ManualResetEvent(false);
Thread MyThread; /// <summary>
/// 委托的消息事件
/// </summary>
/// <param name="nProgress">进度值</param>
private void MessageHandler(int nProgress)
{
lblThreadStatus.Text = "处理: " + Convert.ToString(nProgress);
progressBarThread.Value = nProgress; if (nProgress == progressBarThread.Maximum)
{
MessageBox.Show("Completed");
this.btnTread.Enabled = true;
}
} /// <summary>
/// Handles the Click event of the btnTread control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void btnTread_Click(object sender, EventArgs e)
{
TheDelegate = MessageHandler; StartFrom = Convert.ToInt32(txtStart.Text);
EndTo = Convert.ToInt32(txtEnd.Text); progressBarThread.Minimum = StartFrom;
progressBarThread.Maximum = EndTo; btnTread.Enabled = false; IsThreadPaused = false;
MyThread = new Thread(ProcessRoutine);
MyThread.Start();
} /// <summary>
/// Processes the routine.
/// </summary>
private void ProcessRoutine()
{
for (int nValue = StartFrom; nValue <= EndTo; nValue++)
{
// 判断是否取消
if (CancelEvent.WaitOne(, false) == true)
{
return;
}
this.BeginInvoke(this.TheDelegate, nValue);
Thread.Sleep();
}
} /// <summary>
/// Handles the Click event of the btnCancelThread control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void btnCancelThread_Click(object sender, EventArgs e)
{
btnCancelThread.Enabled = false;
btnPauseThread.Enabled = false; CancelEvent.Set();
MyThread.Join();
} /// <summary>
/// Handles the Click event of the btnPauseThread control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void btnPauseThread_Click(object sender, EventArgs e)
{
// Bad approach!
if (!IsThreadPaused)
{
IsThreadPaused = true;
MyThread.Suspend();
btnPauseThread.Text = "Resume Thread"; // Disallow Cancel
btnCancelThread.Enabled = false;
}
else
{
IsThreadPaused = false;
MyThread.Resume();
btnPauseThread.Text = "Pause Thread";
btnCancelThread.Enabled = true;
}
}
比较起来,两个是完全相同的,对于Thread来说,灵活性就比较好了,BackgroundWorker的使用就相对来说简单了。
线程封装组件(BackgroundWorker)和线程(Thread)的更多相关文章
- Java 线程同步组件 CountDownLatch 与 CyclicBarrier 原理分析
		
1.简介 在分析完AbstractQueuedSynchronizer(以下简称 AQS)和ReentrantLock的原理后,本文将分析 java.util.concurrent 包下的两个线程同步 ...
 - .NET组件程序设计之线程、并发管理(二)
		
.Net组件程序设计之线程.并发管理(二) 2.同步线程 手动同步 监视器 互斥 可等待事件 同步线程 所有的.NET组件都支持在多线程的环境中运行,可以被多个线程并发访问,如果没有线程同步,这样的后 ...
 - .Net组件程序设计之线程、并发管理(一)
		
.Net组件程序设计之线程.并发管理(一) 1.线程 线程 线程的创建 线程的阻塞 线程挂起 线程睡眠 加入线程 线程中止 现在几乎所有的应用程序都是多线程的,给用户看来就是一个应用程序界面(应用程序 ...
 - ThreadExecutorPool 线程池组件
		
ThreadExecutorPool是使用最多的线程池组件: Executor是用来执行提交的Runnable任务的对象,并以接口的形式定义,提供一种提交任务(submission task)与执行任 ...
 - Java带参数的线程类ParameterizedThread——即如何给Thread传递参数
		
在Java中似乎没有提供带运行参数的线程实现类,在第三方类库中也没有找到.网上有大量的文章在讨论这个问题,但都没有提供很好的代码封装解决方案,这令我很吃惊.如果读者知道有官方或者第三方的实现方式,欢迎 ...
 - 创建线程的三种方式(Thread、Runnable、Callable)
		
方式一:继承Thread类实现多线程: 1. 在Java中负责实现线程功能的类是java.lang.Thread 类. 2. 可以通过创建 Thread的实例来创建新的线程. 3. 每个线程都是通过某 ...
 - 创建线程的两种方式比较Thread VS Runnable
		
1.首先来说说创建线程的两种方式 一种方式是继承Thread类,并重写run()方法 public class MyThread extends Thread{ @Override public vo ...
 - Java 线程第三版 第一章Thread导论、 第二章Thread的创建与管理读书笔记
		
第一章 Thread导论 为何要用Thread ? 非堵塞I/O I/O多路技术 轮询(polling) 信号 警告(Alarm)和定时器(Timer) 独立的任务(Ta ...
 - java中的线程问题(三)——继承Thread VS 实现Runnable的区别
		
从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口,如果一定要说它们有什么区别, ...
 
随机推荐
- vue实例属性之el,template,render
			
一.el,template,render属性优先性当Vue选项对象中有render渲染函数时,Vue构造函数将直接使用渲染函数渲染DOM树,当选项对象中没有render渲染函数时,Vue构造函数首先通 ...
 - RMQ问题 [luogu 3865]
			
原题地址 ST表模板题,尝试用单点修改线段树. 原本以为线段树会被卡掉,但是还是险过了.实践证明,快速读入很有用. #include<bits/stdc++.h> using namesp ...
 - Python3之弹性力学——应力张量2
			
问题 已知某应力张量的分量为 \[ \sigma_{11}=3,\quad\sigma_{12} = \sigma_{13} = 1, \quad \sigma_{22} = \sigma_{33} ...
 - 2190 ACM 数学概率论的乘法和加法原则
			
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2190 思路:明显我们要寻找 边长为n和边长为n-1,n-2,n-3·····的规律,这样得出一个递推公式就 ...
 - Ubuntu下常用指令
			
James最近因为需要尝试着编译Android源代码,系统环境变成了Ubuntu.和熟悉Windows操作系统环境一样,都有过渡的阶段.下面记录常用的操作指令. 分类目录如下: uname -a 查看 ...
 - nodejs,koa2常用模块
			
"dependencies": { "multer": "^1.2.0", "node-schedule": " ...
 - Oracle内置函数
			
单行函数:当查询表或试图时每行都能返回一个结果,可用于select,where,order by等子句中. 对于没有目标的select查询用dual表,这个表时真实存在的,每个用户都可以读取. 单行函 ...
 - BZOJ3457 : Ring
			
根据Polya定理: \[ans=\frac{\sum_{d|n}\varphi(d)cal(\frac{n}{d})}{n}\] 其中$cal(n)$表示长度为$n$的无限循环后包含$S$的串的数量 ...
 - vim技巧3
			
yyp复制当前行到下一行ddp剪切当前行到下一行cw:删除当前单词并进入插入模式xp:交换当前字符和右边字符s:删除光标所在的字符并进入插入模式I:在行首开始输入文字并进入插入模式A:在行尾开始输入文 ...
 - JS面向对象之创建对象模式
			
虽然Object构造函数或对象字面量都可以用来创建单个对象,但都有一个缺点,使用同一个接口来创建对象,会产生大量重复的代码,为解决这个问题,引出下列方法 1.工厂模式 抽象了创建具体对象的过程,用函数 ...