背景:

在 WinForms 中,有时要执行耗时的操作,比如统计某个磁盘分区的文件夹或者文件数目,如果分区很大或者文件过多的话,处理不好就会造成“假死”的情况,或者报“线程间操作无效”的异常,或者在该操作未完成之前操作用户界面,会导致用户界面停止响应。

----比如现在学习的MES UI中要查询数据量较大的记录显示在Spread中就可以用BackgroundWorker 类!

解决的方法就是新开一个线程,把耗时的操作放到线程中执行,这样就可以在用户界面上进行其它操作。 如果不借助Thread编程,用户就会感觉界面反映很迟钝。新建线程可以用 Thread 类,可以实现多线程同时操作,简单的可以通过 BackgroundWorker 类实现。 在.Net 2.0中可以通过BackgroundWork非常方便地进行Thread编程,

大致的步骤是:

1、调用BackgroundWorker的RunWorkerAsync方法(可以传递参数),它将引发DoWork事件

2、在DoWork的事件响应代码中调用耗时的操作,是真正的后台处理工作

3、在耗时操作中判断CancellationPending属性,如果为false则退出

4、如果要向用户界面发送信息,则调用BackgroundWorker的ReportProgress方法,它将引发ProgressChanged事件(可以将改变通过object类型传递)

5、在ProgressChanged事件的响应代码中将改变呈现给用户,及运行在主线程中

6、如果需要取消耗时操作,则调用BackgroundWorker的CancelAsync方法,需要和步骤3一起使用

命名空间:
用 BackgroundWorker 类执行耗时的操作
BackgroundWorker 类在 System.ComponentModel 命名空间下。
VS 的工具箱时有一个 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  当后台操作已完成、被取消或引发异常时发生

生命周期中的参数传递:

在整个生命周期内发生了3次重要的参数传递过程:
    参数传递1:此次的参数传递是将RunWorkerAsync(Object)中的Object传递到DoWork事件的DoWorkEventArgs.Argument,由于在这里只有一个参数可以传递,所以在实际应用往封装一个类,将整个实例化的类作为RunWorkerAsync的Object传递到DoWorkEventArgs.Argument;
    参数传递2:此次是将程序运行进度传递给ProgressChanged事件,实际使用中往往使用给方法和事件更新进度条或者日志信息;
    参数传递3:在DoWork事件结束之前,将后台线程产生的结果数据赋给DoWorkEventArgs.Result一边在RunWorkerCompleted事件中调用RunWorkerCompletedEventArgs.Result属性取得后台线程产生的结果。
    看到DoWork事件是在后台线程中运行的,所以在该事件中不能够操作用户界面的内容,如果需要更新用户界面,可以使用ProgressChanged事件及RunWorkCompleted事件来实现。

源代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms; namespace WindowsFormsApp_BackGroundWorker
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent(); //设置能够报告进度更新
//设置能够支持异步取消
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
} //在designer里的属性设计器里直接双击就添加了对backgroundWorker1的ProgressChanged的事件处理程序
//this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
//this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
//this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted); //由ReportProgress方法触发,通过响应消息,来处理界面的显示工作
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//获取异步操作进度百分比,主线程
this.progressBar1.Value = e.ProgressPercentage;
this.label1.Text = e.UserState.ToString();
this.label1.Update(); } //后台工作完成时引发的事件,可以在此事件处理程序里面写进行后续的处理工作,比如提示
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//MessageBox.Show("计算终于完成了!");
if (!e.Cancelled && e.Error == null)
{
MessageBox.Show("处理完成了!" + e.Result);
}
else
{
MessageBox.Show("后台线程被取消或发生异常!");
}
} //此事件由开始按钮里的调用RunWorkerAsync方法引发
//这里就是后台进程开始的地方,调用工作函数的地方,也可以把现有的处理函数写在这里
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Countwork(this.backgroundWorker1);
Countwork(backgroundWorker1);
} //后台处理函数,真正的处理工作
private bool Countwork(BackgroundWorker bw)
{
int n = ;
for (int i = ; i <= n; i++)
{
//判断用户是否执行了取消后台操作,是的话显示返回
if (bw.CancellationPending)
{
bw.ReportProgress(i,string.Format("当前操作值是{0},操作被用户申请中断",i));
return false; }
//ReportProgress函数的作用是,向主线程报告处理进度。折算成百分比,或者把进度条的最大值设置为10000
bw.ReportProgress(i,string.Format("当前值是{0}",i));
}
return true; } private void button_Start_Click(object sender, EventArgs e)
{
//判断是否在进行异步操作,应对用户多次点击开始按钮
if(this.backgroundWorker1.IsBusy)
{
return;
} //触发DOWORK事件,实际就是让后台工作开始
this.backgroundWorker1.RunWorkerAsync();
} //不太好用...
private void button_Cancel_Click(object sender, EventArgs e)
{
this.backgroundWorker1.CancelAsync();
this.backgroundWorker1.Dispose();//释放资源
} private void button_Exit_Click(object sender, EventArgs e)
{
this.Close();
} }
}

运行截图:

以上,本人的学习总结,优秀BLOG参考:

http://blog.itpub.net/23109131/viewspace-670314/

http://blog.163.com/j_yd168/blog/static/4967972820092114269195/   c# BackGroundWorker 多线程操作的小例子

thread学习笔记--BackgroundWorker 类的更多相关文章

  1. Java学习笔记——File类之文件管理和读写操作、下载图片

    Java学习笔记——File类之文件管理和读写操作.下载图片 File类的总结: 1.文件和文件夹的创建 2.文件的读取 3.文件的写入 4.文件的复制(字符流.字节流.处理流) 5.以图片地址下载图 ...

  2. python学习笔记4_类和更抽象

    python学习笔记4_类和更抽象 一.对象 class 对象主要有三个特性,继承.封装.多态.python的核心. 1.多态.封装.继承 多态,就算不知道变量所引用的类型,还是可以操作对象,根据类型 ...

  3. Java学习笔记之---类和对象

    Java学习笔记之---类和对象 (一)类 类是一个模板,它描述一类对象的行为和状态  例如:动物类是一个类,动物们都有属性:颜色,动物们都有行为:吃饭 public class Dog { Stri ...

  4. UML学习笔记:类图

    UML学习笔记:类图 有些问题,不去解决,就永远都是问题! 类图 类图(Class Diagrame)是描述类.接口以及它们之间关系的图,用来显示系统中各个类的静态结构. 类图包含2种元素:类.接口, ...

  5. swift学习笔记3——类、结构体、枚举

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  6. Java学习笔记-File类的基本方法

    要渐渐养成写博客的习惯-----> 前段时间看Mars的java中的I/O流没怎么懂,发现I/O流好难啊.今天重新看一遍其他教学,还有书籍,做些笔记,记录下每天的学习生活. File类的一些方法 ...

  7. CSS3学习笔记——伪类hover

    最近看到一篇文章:“Transition.Transform和Animation使用简介及应用展示”    ,想看看里面 “不同缓动类效果demo”例子的效果,发现了一个问题如下: .Trans_Bo ...

  8. Java7编程 高级进阶学习笔记--嵌套类

    定义: 在一个类中定义的类叫做嵌套类. 作用: 1.允许对相关类进行逻辑分组 2.增强了代码的封装性 3.使代码具有更强的可读性和维护性 使用方式: package com.cmz.baseTest; ...

  9. 初探swift语言的学习笔记四(类对象,函数)

    作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/29606137 转载请注明出处 假设认为文章对你有所帮助,请通过留言 ...

随机推荐

  1. Android零基础入门第25节:最简单最常用的LinearLayout线性布局

    原文:Android零基础入门第25节:最简单最常用的LinearLayout线性布局 良好的布局设计对于UI界面至关重要,在前面也简单介绍过,目前Android中的布局主要有6种,创建的布局文件默认 ...

  2. .net core 利用Selenium和PhantomJS后台生成EChart图片

    1.引用 NuGet安装: Selenium.Support Selenium.WebDriver Selenium.WebDriver.PhantomJS.CrossPlatform  (分布Lin ...

  3. 了解Activity

    Android中的activity全都归属于task管理 .task 是多个 activity 的集合,这些 activity 按照启动顺序排队存入一个栈(即“back stack”).android ...

  4. Dlib 19.4(算法,压缩,图像处理,机器学习,Meta编程,网络,HTTP服务器)

    Algorithms API Wrappers Bayesian Nets Compression Containers Graph Tools Image Processing Linear Alg ...

  5. Qt4学习笔记 (7) 本篇说一下Qt对于脚本的支持, 即QtScript模块.

    本篇说一下Qt对于脚本的支持, 即QtScript模块. Qt支持的脚本基于ECMAScript脚本语言, 这个东西又是javascript, jscript的基础. 所以, 一般只要学过javasc ...

  6. layui打印表格自定义函数

    函数如下 function print (tablelayid) { var v = document.createElement("div"); var f = ["& ...

  7. T4随记

    关于T4模板的信息我就不赘述了,百度一大堆 MSDN的介绍 https://msdn.microsoft.com/zh-cn/library/bb126478.aspx 下面是简单的一个示例,从类中获 ...

  8. SYN591型 多功能数字面板表

       SYN591型 多功能数字面板表 多功能数字面板表数字面板表使用说明视频链接: http://www.syn029.com/h-pd-248-0_310_44_-1.html 请将此链接复制到浏 ...

  9. SYN2136型 北斗NTP网络时间服务器

    SYN2136型  北斗NTP网络时间服务器 北斗NTP网络时间服务器时间服务器使用说明视频链接: http://www.syn029.com/h-pd-109-0_310_36_-1.html 请将 ...

  10. spring boot单元测试之RestTemplate(一)

    写代码重要,写好的代码准确无误,且符合预期那更是必不可少. spring boot内嵌了专门的单元测试模块——RestTemplate,保证了程序员可以对自己的代码进行及时的测试. 闲言少叙,直接上代 ...