先声明,大部分资料均参考网上,进行了整理。

1.

在 VS 中添加了 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 事件来实现。

2. 凡是 WinForm 的应用程序,如果他执行了一个的非常冗长的处理操作(比如文件 查询),

它在执行时会锁定用户界面,虽然主活动窗口 一直在运行,但用户无 法与程序交互,

无法移动窗体或改变窗体大小,所以用户感觉很不爽。如何做才 能使得这个程序有响应。

答案就是在后台线程中执行这个操作。

在这里已经有了多种方法来做这个事情:

(一)  委托异步调用 将具体耗时的操作作为一个委托,并用 BeginInvoke 来异步执行这个委托

(Invoke 是同步调用),并且可以为这个操作传入参数并且通过 EndInvoke 方 法获得返回返回值。

(二)  使用 ThreadPool 新建.net FrameWork 中自带的 WaitCallback 委托,然后放到线程池

中运行 ThreadPool.QueueUserWorkItem( callback ); 根据 WaitCallback 委托的定义,

可以传入一个 object 类型的参数。 但是不能精确的控制线程池中的线程。

(三)  使用 Thread 和 ThreadPool 相比,使用 Thread 的开销会比较大。但是它有它的优势,

使用 Thread 类可以显式管理线程。只要有可能,就应该使用 ThreadPool 类来 创建线程。

然而,在一些情况下,您还是需要创建并管理您自己的线程,而不是 使用 ThreadPool 类。

.net 2.0 中,提供了一个新的委托 ParameterizedThreadStart 支持启动一个线程并传入参数,

这是对原来的 ThreadStart 委托的改进。

说了这么多还没有说到今天的主角 BackgroundWorker,他也是一个在 2.0 中 新增的类,可以用于启动后台

线程,并在后台计算结束后调用主线程 的方法.可 以看出同样的功能使用委托的异步调用也可以实现,只是

使用 BackgroundWorker 的话会更加的简便快捷,可以节省开发时间,

并把你从 创建 自己的委托以及对它们的调用中解救出来。真是这样的吗看看下面这个例子。

其 实我也是从 101Samples 中看到的例子。

先看看 BackgroundWorker 中的主要概念。

第一:主要的事件及参数。

DoWork——当执行 BackgroundWorker.RunWorkerAsync 方法时会触 发该事件,

并且传递 DoWorkEventArgs 参数;

ProgressChanged——操作处理中获得的处理状态变化,

通过 BackgroundWorker.ReportProgress(int)方法 触发该事件,

并且传递 ProgressChangedEventArgs,其中包含了处理的百分比;

RunWorkerCompleted ——异步操作完成后会触发该事件,当然如果需要在操作

过程中结束可以执行 BackgroundWorker.CancelAsync 方法要求异步调用中 止,

并且在异步委托操作中检测 BackgroundWorker.CancellationPending 属性如果 为 true 的话,

跳出异步调用,同时将 DoWorkEventArgs.Cancel 属性设为 true,这样当退出异步调用的时候,

可以让处理 RunWorkerCompleted 事件的函数 知道 是正常退出还是中途退出。

第二:主要的方法。

BackgroundWorker.RunWorkerAsync—— “起动”异步调用的方法有两次重载

RunWorkerAsync(),RunWorkerAsync(object argument),第二个重载提供了一个 参数,

可以供异步调用使用。(如果有多个参数要传递怎么办,使用一个类来传 递他们吧)。

调用该方法后会触发 DoWork 事件,并且为处理 DoWork 事件的函数 DoWorkEventArg 事件

参数,其中包含了 RunWorkerAsync 传递的参数。在相应 DoWork 的处理函数中就可以做具体的复杂操作。

BackgroundWorker.ReportProgress—— 有时候需要在一个冗长的操作中向用户不断反馈进度,这样的话就可 以调用的 ReportProgress(int percent),在调用 ReportProgress 方法时,触 发 ProgressChanged 事件。提供一个在 0 到 100 之间的整数,它表示后台活动 已完成的百分比。你也可能提供任何对象作为第二个参数,允许你 给事件处理 程序传递状态信息。作为传递到此过程的 ProgressChangedEventArgs 参数属 性, 百分比和你自己的对象 (如果提供的话) 均要被传递到 ProgressChanged 事 件处理程序。这些属性被分别命名为 ProgressPercentage 和 UserState,并且 你的事件处理程序可以以任何需要的方式使用它们。(注意:只有在 BackgroundWorker.WorkerReportsProgress 属性被设置为 true 该方法才可用)。

BackgroundWorker.CancelAsync—— 但需要退出异步调用的时候,就调用的这个方法。但是样还不够,因为它仅 仅是将 BackgroudWorker.CancellationPending 属 性设置为 true。你需要在具 体的异步调用处理的时候,不断检查 BackgroudWorker.CancellationPending 是否为 true,如果是真的话就退出。(注意:只有在 BackgroundWorker.WorkerSupportsCancellation 属性被设置为 true 该方法才 可用)。

具体代码示例可以在博客中找到!

示例代码下载地址http://files.cnblogs.com/dudg/BackgroudWokerUI.rar

C# BackgroundWorker详解,图例,原理分析的更多相关文章

  1. Block详解二(底层分析)

    Block专辑: Block讲解一 MRC-block与ARC-block Block详解一(底层分析) 今天讲述Block的最后一篇,后两篇仅仅是加深1,2篇的理解,废话少说,开始讲解! __blo ...

  2. 关于syslog日志功能详解 事件日志分析、EventLog Analyzer

    关于syslog日志功能详解 事件日志分析.EventLog Analyzer 一.日志管理 保障网络安全 Windows系统日志分析 Syslog日志分析 应用程序日志分析 Windows终端服务器 ...

  3. Java性能分析之线程栈详解与性能分析

    Java性能分析之线程栈详解 Java性能分析迈不过去的一个关键点是线程栈,新的性能班级也讲到了JVM这一块,所以本篇文章对线程栈进行基础知识普及以及如何对线程栈进行性能分析. 基本概念 线程堆栈也称 ...

  4. WPF 后台任务 等待动画 样例 && C# BackgroundWorker 详解

    运行效果: 前台代码: <Window x :Class="Waiting.Window1" xmlns="http://schemas.microsoft.com ...

  5. ArrayList详解-源码分析

    ArrayList详解-源码分析 1. 概述 在平时的开发中,用到最多的集合应该就是ArrayList了,本篇文章将结合源代码来学习ArrayList. ArrayList是基于数组实现的集合列表 支 ...

  6. LinkedList详解-源码分析

    LinkedList详解-源码分析 LinkedList是List接口的第二个具体的实现类,第一个是ArrayList,前面一篇文章已经总结过了,下面我们来结合源码,学习LinkedList. 基于双 ...

  7. 线段树详解 (原理,实现与应用)(转载自:http://blog.csdn.net/zearot/article/details/48299459)

    原文地址:http://blog.csdn.net/zearot/article/details/48299459(如有侵权,请联系博主,立即删除.) 线段树详解    By 岩之痕 目录: 一:综述 ...

  8. UEFI启动视频详解:启动分析+N项操作实例

    ============================================================= ※※※※最给力的视频解说※※※※ 2011hiboy全部共享资料:立刻去   ...

  9. Shiro的Filter机制详解---源码分析

    Shiro的Filter机制详解 首先从spring-shiro.xml的filter配置说起,先回答两个问题: 1, 为什么相同url规则,后面定义的会覆盖前面定义的(执行的时候只执行最后一个). ...

随机推荐

  1. 开发现代ASP.NET应用程序

    新思想.新技术.新架构——更好更快的开发现代ASP.NET应用程序(续1)   今天在@张善友和@田园里的蟋蟀的博客看到微软“.Net社区虚拟大会”dotnetConf2015的信息,感谢他们的真诚付 ...

  2. C语言练手自己编写学生成绩管理系统

    #include<stdio.h> #include<stdlib.h> /*定义学生结构体*/ struct Student { ]; ]; float Mark1; flo ...

  3. 剖析Jetty实现原理

    之前写一个简单易用Jetty文章.Jetty对于做JAVA Web发展的方面来说并不陌生,他是一个servlet集装箱,只有相对Tomcat这是比较简单的设计,并且也相对简单,使用灵活,我是学习和使用 ...

  4. 如何使用Visual Studio 2013 开发PHP5.6项目

    原文如何使用Visual Studio开发PHP项目 在windows下开发php除了记事本 DW 以及一帮Zend studio,Eclipse,NetBeans之流以外,个人感觉还是vsiual ...

  5. windows系统下c语言暂停程序

    原文:windows系统下c语言暂停程序 windows系统下,很多C语言初学者的调试时,往往没看到结果程序就退出了,据我所知的方法主要有以下几种 方法一: #include int main() { ...

  6. PDFBox之文档创建

    1.创建一个空的PDF 下面的小例子表示如何使用PDFBox来创建一个新的PDF文档. // 创建一个空的文档 PDDocument document = new PDDocument(); // 创 ...

  7. [ext/iconv/iconv.lo] Error 1

    办法1: wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz tar -zxvf libiconv-1.13.1.tar.g ...

  8. idea中ajax中文乱码

    case:@RequestMapping中添加 produces= "text/plain;charset=UTF-8", @RequestMapping(method = Req ...

  9. SWAT—Samba WEB管理工具

    本文试验环境是RHEL5.2+samba-swat-3.0.28.Server的IP是192.168.120.241.   1. swat介绍 SWAT:The Samba WEB Administr ...

  10. beanutils中Lazy

    public class LazyBean { //    public static void main(String[] args) {//        DynaBean dynaBean=ne ...