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)的更多相关文章

  1. Java 线程同步组件 CountDownLatch 与 CyclicBarrier 原理分析

    1.简介 在分析完AbstractQueuedSynchronizer(以下简称 AQS)和ReentrantLock的原理后,本文将分析 java.util.concurrent 包下的两个线程同步 ...

  2. .NET组件程序设计之线程、并发管理(二)

    .Net组件程序设计之线程.并发管理(二) 2.同步线程 手动同步 监视器 互斥 可等待事件 同步线程 所有的.NET组件都支持在多线程的环境中运行,可以被多个线程并发访问,如果没有线程同步,这样的后 ...

  3. .Net组件程序设计之线程、并发管理(一)

    .Net组件程序设计之线程.并发管理(一) 1.线程 线程 线程的创建 线程的阻塞 线程挂起 线程睡眠 加入线程 线程中止 现在几乎所有的应用程序都是多线程的,给用户看来就是一个应用程序界面(应用程序 ...

  4. ThreadExecutorPool 线程池组件

    ThreadExecutorPool是使用最多的线程池组件: Executor是用来执行提交的Runnable任务的对象,并以接口的形式定义,提供一种提交任务(submission task)与执行任 ...

  5. Java带参数的线程类ParameterizedThread——即如何给Thread传递参数

    在Java中似乎没有提供带运行参数的线程实现类,在第三方类库中也没有找到.网上有大量的文章在讨论这个问题,但都没有提供很好的代码封装解决方案,这令我很吃惊.如果读者知道有官方或者第三方的实现方式,欢迎 ...

  6. 创建线程的三种方式(Thread、Runnable、Callable)

    方式一:继承Thread类实现多线程: 1. 在Java中负责实现线程功能的类是java.lang.Thread 类. 2. 可以通过创建 Thread的实例来创建新的线程. 3. 每个线程都是通过某 ...

  7. 创建线程的两种方式比较Thread VS Runnable

    1.首先来说说创建线程的两种方式 一种方式是继承Thread类,并重写run()方法 public class MyThread extends Thread{ @Override public vo ...

  8. Java 线程第三版 第一章Thread导论、 第二章Thread的创建与管理读书笔记

    第一章 Thread导论 为何要用Thread ? 非堵塞I/O      I/O多路技术      轮询(polling)      信号 警告(Alarm)和定时器(Timer) 独立的任务(Ta ...

  9. java中的线程问题(三)——继承Thread VS 实现Runnable的区别

    从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口,如果一定要说它们有什么区别, ...

随机推荐

  1. DevOps: CLM, RLM, RPM, RPD, BSA, BAA, BMA - WOW!

    1. BMC Release Lifecycle Management (RLM) is our suite targeted at managing and automating applicati ...

  2. shell delete with line number

    If you want to delete lines 5 through 10 and 12: sed -e '5,10d;12d' file This will print the results ...

  3. python Event对象、队列和多进程基础

    Event对象 用于线程间通信,即程序中的其一个线程需要通过判断某个线程的状态来确定自己下一步的操作,就用到了event对象 event对象默认为假(Flase),即遇到event对象在等待就阻塞线程 ...

  4. [JOISC2014]電圧

    [JOISC2014]電圧 题目大意: 一个\(n(n\le10^5)\)个点,\(m(m\le2\times10^5)\)条边的无向图.要在图中找到一条边,满足去掉这条边后,剩下的图是一个二分图,且 ...

  5. 20172327 2018-2019-1 《第一行代码Android》第二章学习总结

    学号 2017-2018-2 <第一行代码Android>第二章学习总结 教材学习内容总结 - 活动是什么: 活动(Activity)是最容易吸引用户的地方,它是一种可以包含用户界面的组件 ...

  6. JS 函数表达式

    定义函数的方式有两种, 一种是函数声明,一种就是函数表达式了 函数声明最常见了, sayHi(); // 函数声明会发生提升 function sayHi () { alert('Hi') } 函数表 ...

  7. 【容斥+组合数】Massage @2018acm徐州邀请赛 E

    问题 E: Massage 时间限制: 1 Sec  内存限制: 64 MB 题目描述 JSZKC  feels  so  bored  in  the  classroom  that  he  w ...

  8. IO流(5)—缓冲流

    1.IO体系: 抽象基类--节点流(文件流)--缓冲流(处理流的一种) InputStream --FileInputStream--BufferedInputStream OutputStream- ...

  9. jQuery 学习(1)——认识jQuery

    1.下载 下载地址:http://jquery.com/download/ jquery-3.2.1.js——用于开发和学习(229K) jquery-3.2.1.min.js——用于项目和产品(31 ...

  10. Mac流量监控/硬盘监控小工具

    效果: 中文版: https://member.ipmu.jp/yuji.tachikawa/MenuMetersElCapitan/ 官方版: https://github.com/yujitach ...