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. vue实例属性之el,template,render

    一.el,template,render属性优先性当Vue选项对象中有render渲染函数时,Vue构造函数将直接使用渲染函数渲染DOM树,当选项对象中没有render渲染函数时,Vue构造函数首先通 ...

  2. RMQ问题 [luogu 3865]

    原题地址 ST表模板题,尝试用单点修改线段树. 原本以为线段树会被卡掉,但是还是险过了.实践证明,快速读入很有用. #include<bits/stdc++.h> using namesp ...

  3. Python3之弹性力学——应力张量2

    问题 已知某应力张量的分量为 \[ \sigma_{11}=3,\quad\sigma_{12} = \sigma_{13} = 1, \quad \sigma_{22} = \sigma_{33} ...

  4. 2190 ACM 数学概率论的乘法和加法原则

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2190 思路:明显我们要寻找 边长为n和边长为n-1,n-2,n-3·····的规律,这样得出一个递推公式就 ...

  5. Ubuntu下常用指令

    James最近因为需要尝试着编译Android源代码,系统环境变成了Ubuntu.和熟悉Windows操作系统环境一样,都有过渡的阶段.下面记录常用的操作指令. 分类目录如下: uname -a 查看 ...

  6. nodejs,koa2常用模块

    "dependencies": { "multer": "^1.2.0", "node-schedule": " ...

  7. Oracle内置函数

    单行函数:当查询表或试图时每行都能返回一个结果,可用于select,where,order by等子句中. 对于没有目标的select查询用dual表,这个表时真实存在的,每个用户都可以读取. 单行函 ...

  8. BZOJ3457 : Ring

    根据Polya定理: \[ans=\frac{\sum_{d|n}\varphi(d)cal(\frac{n}{d})}{n}\] 其中$cal(n)$表示长度为$n$的无限循环后包含$S$的串的数量 ...

  9. vim技巧3

    yyp复制当前行到下一行ddp剪切当前行到下一行cw:删除当前单词并进入插入模式xp:交换当前字符和右边字符s:删除光标所在的字符并进入插入模式I:在行首开始输入文字并进入插入模式A:在行尾开始输入文 ...

  10. JS面向对象之创建对象模式

    虽然Object构造函数或对象字面量都可以用来创建单个对象,但都有一个缺点,使用同一个接口来创建对象,会产生大量重复的代码,为解决这个问题,引出下列方法 1.工厂模式 抽象了创建具体对象的过程,用函数 ...