BackgroundWorker是·net里用来执行多线程任务的控件,它允许编程者在一个单独的线程上执行一些操作。

可以通过编程方式创建 BackgroundWorker,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。 如果在 Windows 窗体设计器中创建 BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。

常用方法

  1. RunWorkerAsync 开始执行后台操作。引发 DoWork 事件。
       public void RunWorkerAsync(); //启动线程,触发DoWork事件
       public void RunWorkerAsync(object argument);
  2. CancelAsync 请求取消挂起的后台操作。
    注意:这个方法是将 CancellationPending 属性设置为 true,并不会终止后台操作。在后台操作中要检查CancellationPending 属性,来决定是否要继续执行耗时的操作。
  3. ReportProgress引发 ProgressChanged 事件。
       public void ReportProgress(int percentProgress); //报告进度,触发ProgressChanged事件
       public void ReportProgress(int percentProgress, object userState);

常用属性

  1. IsBusy:  //只读属性,用来判断当前线程是否正在工作中。
  2. CancellationPending: 指示应用程序是否已请求取消后台操作。只读属性,默认为 false,当执行了 CancelAsync 方法后,值为 true。
  3. WorkerSupportsCancellation:指示是否支持异步取消。要执行 CancelAsync 方法,需要先设置该属性为 true。
  4. WorkerReportsProgress:指示是否能报告进度。要执行 ReportProgress 方法,需要先设置该属性为 true。

常用事件

  1. DoWork: 调用 RunWorkerAsync 方法时发生。
  2. ProgressChanged:可选,调用 ReportProgress 方法时发生。
  3. RunWorkerCompleted:可选,后台操作已完成、被取消或引发异常时发生。

注意:在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和RunWorkerCompleted 事件与用户界面进行通信。

  如果想在 DoWork 事件处理程序中和用户界面的控件通信,可在用 ReportProgress 方法。ReportProgress(int percentProgress, object userState),可以传递一个对象。ProgressChanged 事件可以从参数ProgressChangedEventArgs 类的UserState 属性得到这个信息对象。这个事件也可以实现进度条功能,把任务的进度实时呈现给用户。

简单的程序用BackgroundWorker 比 Thread 方便,Thread中和用户界面上的控件通信比较麻烦,需要用委托来调用控件的 Invoke 或BeginInvoke 方法,没有 BackgroundWorker 方便。

使用backgroundWorker步骤

  • 新建BackgroundWorder对象;

  • 根据需求, 设置是否能取消(WorkerSupportsCancellation)、是否报告进度(WorkerReportsProgress);

  • 根据需求,设置好相关事件,DoWorker、ProgressChanged、ProgressChanged;

  • 调用RunWorkerAsyns()方法,启动线程;

  • 在需要取消的位置,判断CancellationPending的值,并做相关处理;//可选

  • 在适当的位置调用ReportProgress(int percentProgress)方法,报告进度。

BackgroundWorker实例

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent(); backgroundWorker1.WorkerReportsProgress = true;//报告完成进度
backgroundWorker1.WorkerSupportsCancellation = true;//允许用户终止后台线程
//绑定事件
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted); }
//开始按钮
private void button1_Click(object sender, EventArgs e)
{
if (!backgroundWorker1.IsBusy)//判断backgroundWorker1是否正在运行异步操作
{
backgroundWorker1.RunWorkerAsync(1000);//开始执行后台异步操作,调用DoWork事件
}
while (backgroundWorker1.IsBusy)//等待后台运行完毕
{
Application.DoEvents();
}
MessageBox.Show("操作完成");
} //取消按钮
private void button2_Click(object sender, EventArgs e)
{
if (backgroundWorker1.WorkerSupportsCancellation == true)
{
backgroundWorker1.CancelAsync();//取消后台操作
backgroundWorker1.Dispose();//释放资源
}
} //DoWork事件声明要执行的耗时操作
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker backgroundWorker = sender as BackgroundWorker;
e.Result = ListNumber(backgroundWorker, e);//运算结果保存在e.Result中(在RunWorkerCompleted事件可能会使用到)
} bool ListNumber(object sender, DoWorkEventArgs e)
{
int num = (int)e.Argument;//接收传入的参数,即RunWorkerAsync(object argument)传入的值
for (int i = 1; i <= num; i++)
{
if (backgroundWorker1.CancellationPending)//判断是否请求了取消后台操作,如果为false则退出
{
e.Cancel = true;//e.Cancel 是否应该取消事件
return false;
}
Thread.Sleep(10);//执行一个耗时操作
backgroundWorker1.ReportProgress(i * 100 / num, i);//报告完成进度 }
return true;
} private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{ progressBar1.Value = e.ProgressPercentage;//将完成进度数据传给进度条
label1.Text = e.ProgressPercentage + "%";
//将中间计算结果在ListBox控件中显示出来
listBox1.Items.Add(e.UserState);//接收ReportProgress方法传递过来的userState
} private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true) //e.Cancelled指示异步操作是否已被取消
{
MessageBox.Show("Canceled!");
}
else if (e.Error != null) //e.Error 指示异步操作期间发生的错误
{
MessageBox.Show("Error: " + e.Error.Message);
}
else
{
MessageBox.Show(e.Result.ToString()); //e.Result 获取异步操作结果的值,即DoWork事件中,Result设置的值。
} }
}

对Winform窗体控件进行安全调用

(WinForm中实现多线程的首选方法是backgroundWorker)

Thread thread = new Thread(SetLabel);//另开一个线程上设置Label的属性
thread.Start(); delegate void Action(string args);//Net3.5自带的Action无参数无返回值
private void SetLabel()
{
Action action = delegate (string args)
{
this.label1.Text = args;
};
if (this.InvokeRequired)//判断当前代码是运行于创建该控件的线程之上,还是运行于另一个线程之上。
this.Invoke(action, "XXX");//注意控件的Inovoke和BeginInvoke委托的方法都执行在UI线程上。对Control的Invoke方法可以使用一个简单的系统委托MethodInvoker无参数返回Void调用。
else
action("XXX");
}

BackGroundWorker组件使用、Winform控件的Invoke安全调用的更多相关文章

  1. winform快速开发平台 -> 基础组件之分页控件

    一个项目控件主要由及部分的常用组件,当然本次介绍的是通用分页控件. 处理思想:我们在处理分页过程中主要是针对数据库操作. 一般情况主要是传递一些开始位置,当前页数,和数据总页数以及相关关联的业务逻辑. ...

  2. C#中的BackgroundWorker控件+Delegate.Invoke (委托同步调用)

    C#中的BackgroundWorker控件+Delegate.Invoke (委托同步调用) 简单代码,记录一下.一个BackgroundWorker控件  backgroundWorkerRefr ...

  3. C#中常见的winform控件命名规范

    我们知道Button 常常简称为btn,那么Winform中的其它控件呢,这篇文章在C#的winform控件命名规范 的基础上对一些控件的名称的简称进行了整理. 1. 标准控件 NO. 控件类型简写 ...

  4. C#中常见的winform控件命名规范 转

    我们知道Button 常常简称为btn,那么Winform中的其它控件呢,这篇文章在C#的winform控件命名规范 的基础上对一些控件的名称的简称进行了整理. 1. 标准控件 NO. 控件类型简写 ...

  5. WinForm控件TreeView 只部分节点显示 CheckBox

    WinForm控件TreeView 只部分节点显示  CheckBox 用过asp.net的应该知道,要在treeview中实现上述功能可以使用ShowCheckBox 属性指定那些节点显示check ...

  6. WinForm控件使用文章收藏整理完成

    对C# WinForm开发系列收集的控件使用方面进行整理, 加入了一些文章, 不断补充充实, 完善这方面. 基础 - 常用控件 C# WinForm开发系列 - CheckBox/Button/Lab ...

  7. [转] c#中 多线程访问winform控件

    原文 c#中多线程访问winform控件的若干问题小结 我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来解决这个问题,下面我将详细的 ...

  8. 多线程访问winform控件出现异常的解决方法

    一.  多线程访问winform控件出现异常的解决方法 1.  问题描述<1> 如果创建某控件的线程之外的其他线程试图调用该控件,则会引发一个 InvalidOperationExcept ...

  9. C# WinForm控件、自定义控件整理(大全)

    转:http://www.cnblogs.com/top5/archive/2010/04/29/1724039.html 对C# WinForm开发系列收集的控件使用方面进行整理, 加入了一些文章, ...

随机推荐

  1. 强制执行父类下的__init__

    两种方式: 1.super(子类,self)__init__() 2.子类.__init__(self) 推荐使用super

  2. STM32固件库模板下载以及固件库学习方法

    固件库模板下载 固件库模板新建过程: 下载我们上节的固件库文件 电脑新建一个文件夹命名为Fwlib-Template,在此文件夹下分别新建DOC Libraries Project User 这四个文 ...

  3. 基于laravel框架构建最小内容管理系统

    校园失物招领平台开发 --基于laravel框架构建最小内容管理系统 摘要 ​ 针对目前大学校园人口密度大.人群活动频繁.师生学习生活等物品容易遗失的基本现状,在分析传统失物招领过程中的工作效率低下. ...

  4. css 清除浮动 & BFC

    前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 文档流的概念:html 中 block 块元素默认是单独占据一行的,从上到下排列,也就是我们说的文档流. ...

  5. pymongo基础使用方法

    本文通过文章同步功能推送至博客园,排版可能会有所错误,敬请见谅! 1.客户端初始化 初始化MongoDB客户端 client = pymongo.MongoClient('localhost',270 ...

  6. (十二)Activitivi5之流程控制网关:排他

    一.概念 所谓排他网关 顾名思义 执行到该网关,根据条件只能走一条执行线 二.案例 当流程走到“学生请假”任务节点的时候, /** * 完成任务 */ @Test public void test_c ...

  7. (六)授权(下):自定义permission

    一.Authorizer.PermissionResolver及RolePermissionResolver Authorizer的职责是进行授权(访问控制),是Shiro API中授权核心的入口点, ...

  8. 数据库及MySQL基础(1)

    1.数据库概述 关系型数据库:面对关系,Java面向对象. ·常见数据库 Oracle(神喻):甲骨文 DB2:IBM SQL Server:微软 Sybase:赛尔斯 MySQL:甲骨文,最早是开源 ...

  9. java调用.net的webservice接口

    要调用webservice,首先得有接口,用已经写好的接口地址在myEclipse的目标project中,右键->new web service client-> 选择JAX-WS方式,点 ...

  10. 关于微信小程序使用watch监听数据变化的方法

    众所周知,Vue中,可以使用监听属性 watch来观察和响应 Vue 实例上的数据变化,那么小程序能不能实现这一点呢? 监听器的原理,是将data中需监听的数据写在watch对象中,并给其提供一个方法 ...