BackGroundWorker组件使用、Winform控件的Invoke安全调用
BackgroundWorker是·net里用来执行多线程任务的控件,它允许编程者在一个单独的线程上执行一些操作。
可以通过编程方式创建 BackgroundWorker,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。 如果在 Windows 窗体设计器中创建 BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
常用方法
- RunWorkerAsync 开始执行后台操作。引发 DoWork 事件。
public void RunWorkerAsync(); //启动线程,触发DoWork事件
public void RunWorkerAsync(object argument); - CancelAsync 请求取消挂起的后台操作。
注意:这个方法是将 CancellationPending 属性设置为 true,并不会终止后台操作。在后台操作中要检查CancellationPending 属性,来决定是否要继续执行耗时的操作。 - ReportProgress引发 ProgressChanged 事件。
public void ReportProgress(int percentProgress); //报告进度,触发ProgressChanged事件
public void ReportProgress(int percentProgress, object userState);
常用属性
- IsBusy: //只读属性,用来判断当前线程是否正在工作中。
- CancellationPending: 指示应用程序是否已请求取消后台操作。只读属性,默认为 false,当执行了 CancelAsync 方法后,值为 true。
- WorkerSupportsCancellation:指示是否支持异步取消。要执行 CancelAsync 方法,需要先设置该属性为 true。
- WorkerReportsProgress:指示是否能报告进度。要执行 ReportProgress 方法,需要先设置该属性为 true。
常用事件
- DoWork: 调用 RunWorkerAsync 方法时发生。
- ProgressChanged:可选,调用 ReportProgress 方法时发生。
- 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安全调用的更多相关文章
- winform快速开发平台 -> 基础组件之分页控件
一个项目控件主要由及部分的常用组件,当然本次介绍的是通用分页控件. 处理思想:我们在处理分页过程中主要是针对数据库操作. 一般情况主要是传递一些开始位置,当前页数,和数据总页数以及相关关联的业务逻辑. ...
- C#中的BackgroundWorker控件+Delegate.Invoke (委托同步调用)
C#中的BackgroundWorker控件+Delegate.Invoke (委托同步调用) 简单代码,记录一下.一个BackgroundWorker控件 backgroundWorkerRefr ...
- C#中常见的winform控件命名规范
我们知道Button 常常简称为btn,那么Winform中的其它控件呢,这篇文章在C#的winform控件命名规范 的基础上对一些控件的名称的简称进行了整理. 1. 标准控件 NO. 控件类型简写 ...
- C#中常见的winform控件命名规范 转
我们知道Button 常常简称为btn,那么Winform中的其它控件呢,这篇文章在C#的winform控件命名规范 的基础上对一些控件的名称的简称进行了整理. 1. 标准控件 NO. 控件类型简写 ...
- WinForm控件TreeView 只部分节点显示 CheckBox
WinForm控件TreeView 只部分节点显示 CheckBox 用过asp.net的应该知道,要在treeview中实现上述功能可以使用ShowCheckBox 属性指定那些节点显示check ...
- WinForm控件使用文章收藏整理完成
对C# WinForm开发系列收集的控件使用方面进行整理, 加入了一些文章, 不断补充充实, 完善这方面. 基础 - 常用控件 C# WinForm开发系列 - CheckBox/Button/Lab ...
- [转] c#中 多线程访问winform控件
原文 c#中多线程访问winform控件的若干问题小结 我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来解决这个问题,下面我将详细的 ...
- 多线程访问winform控件出现异常的解决方法
一. 多线程访问winform控件出现异常的解决方法 1. 问题描述<1> 如果创建某控件的线程之外的其他线程试图调用该控件,则会引发一个 InvalidOperationExcept ...
- C# WinForm控件、自定义控件整理(大全)
转:http://www.cnblogs.com/top5/archive/2010/04/29/1724039.html 对C# WinForm开发系列收集的控件使用方面进行整理, 加入了一些文章, ...
随机推荐
- Windows删除某服务
win+R然后cmd进入命令窗口 sc delete 服务名
- 【转】Entity Framework简介
Entity Framework Core 可基于现有数据库创建模型,也可基于模型创建数据库. 以下文字来源于:http://www.entityframeworktutorial.net/what- ...
- 什么是H5?
总听到很多人说H5,现在H5很火,到底H5是什么,以下发表个人对H5的理解. HTML5 将成为 HTML.XHTML 以及 HTML DOM 的新标准. HTML 的上一个版本诞生于 1999 年. ...
- java输入输出 -- Java NIO之选择器
一.简介 前面的文章说了缓冲区,说了通道,本文就来说说 NIO 中另一个重要的实现,即选择器 Selector.在更早的文章中,我简述了几种 IO 模型.如果大家看过之前的文章,并动手写过代码的话.再 ...
- [NOIP普及组2011]装箱问题
目录 链接 博客链接 题目链接 题目内容 题目描述 格式 输入 输出 样例 输入 输出 前缀知识 题解 题目名称:装箱问题 来源:2011年NOIP普及组 链接 博客链接 CSDN 洛谷博客 题目链接 ...
- QT QcustomPlot的简单使用
第一步.QcustomPlot是QT提供的一个第三方库,在使用前需要在QcustomPlot官网上进行下载. 第二步.把解压完的QcustomPlot压缩包中的qcustomplot.h和qcusto ...
- 防止vi粘贴时自动添加缩进的方法
使用Xshell连接Linux服务器,使用vi打开文件进行粘贴时,会自动在行首添加很多空格,导致格式错乱.可以用如下方法剞劂 在拷贝前输入:set paste (这样的话,vim就不会启动自动缩进,而 ...
- YAML 语言格式
1. 认识 YAML YAML(Yet Another Markup Language)语言(发音 /ˈjæməl/ )是一个类似 XML.JSON 的标记性语言.YAML 强调以数据为中心,并不是以 ...
- root用户和sudo使用root权限的区别(转)
百度百科:https://baike.baidu.com/item/sudo/7337623?fr=aladdin sudo指令 功能: 以root的身分执行命令 语法: sudo 其他指令 用户: ...
- (六)CXF之自定义拦截器
一.需求分析 客户端在调用服务端的方法时,需要进行用户名和密码验证.此时分为: 客户端请求的时候,要发送用户名密码到服务端 服务端检验用户名密码. 二.案例 前提:本章案例是基于前一章节的例子进一步讲 ...