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实例

  1. public partial class Form1 : Form
  2. {
  3. public Form1()
  4. {
  5. InitializeComponent();
  6.  
  7. backgroundWorker1.WorkerReportsProgress = true;//报告完成进度
  8. backgroundWorker1.WorkerSupportsCancellation = true;//允许用户终止后台线程
  9. //绑定事件
  10. backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
  11. backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
  12. backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
  13.  
  14. }
  15. //开始按钮
  16. private void button1_Click(object sender, EventArgs e)
  17. {
  18. if (!backgroundWorker1.IsBusy)//判断backgroundWorker1是否正在运行异步操作
  19. {
  20. backgroundWorker1.RunWorkerAsync(1000);//开始执行后台异步操作,调用DoWork事件
  21. }
  22. while (backgroundWorker1.IsBusy)//等待后台运行完毕
  23. {
  24. Application.DoEvents();
  25. }
  26. MessageBox.Show("操作完成");
  27. }
  28.  
  29. //取消按钮
  30. private void button2_Click(object sender, EventArgs e)
  31. {
  32. if (backgroundWorker1.WorkerSupportsCancellation == true)
  33. {
  34. backgroundWorker1.CancelAsync();//取消后台操作
  35. backgroundWorker1.Dispose();//释放资源
  36. }
  37. }
  38.  
  39. //DoWork事件声明要执行的耗时操作
  40. private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
  41. {
  42. BackgroundWorker backgroundWorker = sender as BackgroundWorker;
  43. e.Result = ListNumber(backgroundWorker, e);//运算结果保存在e.Result中(在RunWorkerCompleted事件可能会使用到)
  44. }
  45.  
  46. bool ListNumber(object sender, DoWorkEventArgs e)
  47. {
  48. int num = (int)e.Argument;//接收传入的参数,即RunWorkerAsync(object argument)传入的值
  49. for (int i = 1; i <= num; i++)
  50. {
  51. if (backgroundWorker1.CancellationPending)//判断是否请求了取消后台操作,如果为false则退出
  52. {
  53. e.Cancel = true;//e.Cancel 是否应该取消事件
  54. return false;
  55. }
  56. Thread.Sleep(10);//执行一个耗时操作
  57. backgroundWorker1.ReportProgress(i * 100 / num, i);//报告完成进度
  58.  
  59. }
  60. return true;
  61. }
  62.  
  63. private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
  64. {
  65.  
  66. progressBar1.Value = e.ProgressPercentage;//将完成进度数据传给进度条
  67. label1.Text = e.ProgressPercentage + "%";
  68. //将中间计算结果在ListBox控件中显示出来
  69. listBox1.Items.Add(e.UserState);//接收ReportProgress方法传递过来的userState
  70. }
  71.  
  72. private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  73. {
  74. if (e.Cancelled == true) //e.Cancelled指示异步操作是否已被取消
  75. {
  76. MessageBox.Show("Canceled!");
  77. }
  78. else if (e.Error != null) //e.Error 指示异步操作期间发生的错误
  79. {
  80. MessageBox.Show("Error: " + e.Error.Message);
  81. }
  82. else
  83. {
  84. MessageBox.Show(e.Result.ToString()); //e.Result 获取异步操作结果的值,即DoWork事件中,Result设置的值。
  85. }
  86.  
  87. }
  88. }

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

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

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

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. Windows删除某服务

    win+R然后cmd进入命令窗口 sc delete 服务名

  2. 【转】Entity Framework简介

    Entity Framework Core 可基于现有数据库创建模型,也可基于模型创建数据库. 以下文字来源于:http://www.entityframeworktutorial.net/what- ...

  3. 什么是H5?

    总听到很多人说H5,现在H5很火,到底H5是什么,以下发表个人对H5的理解. HTML5 将成为 HTML.XHTML 以及 HTML DOM 的新标准. HTML 的上一个版本诞生于 1999 年. ...

  4. java输入输出 -- Java NIO之选择器

    一.简介 前面的文章说了缓冲区,说了通道,本文就来说说 NIO 中另一个重要的实现,即选择器 Selector.在更早的文章中,我简述了几种 IO 模型.如果大家看过之前的文章,并动手写过代码的话.再 ...

  5. [NOIP普及组2011]装箱问题

    目录 链接 博客链接 题目链接 题目内容 题目描述 格式 输入 输出 样例 输入 输出 前缀知识 题解 题目名称:装箱问题 来源:2011年NOIP普及组 链接 博客链接 CSDN 洛谷博客 题目链接 ...

  6. QT QcustomPlot的简单使用

    第一步.QcustomPlot是QT提供的一个第三方库,在使用前需要在QcustomPlot官网上进行下载. 第二步.把解压完的QcustomPlot压缩包中的qcustomplot.h和qcusto ...

  7. 防止vi粘贴时自动添加缩进的方法

    使用Xshell连接Linux服务器,使用vi打开文件进行粘贴时,会自动在行首添加很多空格,导致格式错乱.可以用如下方法剞劂 在拷贝前输入:set paste (这样的话,vim就不会启动自动缩进,而 ...

  8. YAML 语言格式

    1. 认识 YAML YAML(Yet Another Markup Language)语言(发音 /ˈjæməl/ )是一个类似 XML.JSON 的标记性语言.YAML 强调以数据为中心,并不是以 ...

  9. root用户和sudo使用root权限的区别(转)

    百度百科:https://baike.baidu.com/item/sudo/7337623?fr=aladdin sudo指令 功能: 以root的身分执行命令 语法: sudo 其他指令 用户: ...

  10. (六)CXF之自定义拦截器

    一.需求分析 客户端在调用服务端的方法时,需要进行用户名和密码验证.此时分为: 客户端请求的时候,要发送用户名密码到服务端 服务端检验用户名密码. 二.案例 前提:本章案例是基于前一章节的例子进一步讲 ...