BackgroundWorker控件
在我们的程序中,经常会有一些耗时较长的运算,为了保证用户体验,不引起界面不响应,我们一般会采用多线程操作,让耗时操作在后台完成,完成后再进行处理或给出提示,在运行中,也会时时去刷新界面上的进度条等显示,必要时还要控制后台线程中断当前操作。
在.net中,提供了一个组件BackgroundWorker就是专门解决这个问题的。BackgroundWorker类允许在单独的专用线程上运行操作。 耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面(UI)似乎处于停止响应状态。如果需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用BackgroundWorker类方便地解决问题。
程序执行步骤:
1、调用BackgroundWorker的RunWorkerAsync()方法,如果后台操作需要参数,在调用RunWorkerAsync()方法时给出参数,在DoWork事件处理程序内部,可以从DoWorkEventArgs.Argument属性中提取该参数。
2、执行DoWork事件,后台需要执行的代码放到DoWork事件里面执行。当调用RunWorkerAsync()方法时,BackgroundWorker通过触发DoWork事件,开始执行后台操作
显示后台操作进度:
为了显示后台操作的执行进度,首先要使WorkerReportsProgress等于true,然后调用BackgroundWorker的ReportProgress()方法,通过它传递操作完成的进度值,此外,该方法触发ProgressChanged事件,在此事件中,通过ProgressChangedEventArgs的实例,接收到主线程传递过来的参数。
取消后台操作:
为了使 BackgroundWorker 可以取消后台正在执行的操作,首先要把属性WorkerSupportsCancellation 的值设置为 true。接着调用CancelAsync()方法,该方法使得属性CancellationPending 为true,利用CancellationPending 属性,可以判断是否取消后台异步操作。
后台操作完成后,反馈给用户:
当后台操作完成以后,无论是completed 还是cancelled,RunWorkerCompleted()事件都会被触发,通过此方法可以将后台操作的完成结果反馈给用户。RunWorkerCompleted 事件处理函数会在DoWork 事件处理函数返回后被调用。通过它我们可以进行一些运算结束后的操作,比如禁用取消按钮,异常处理,结果显示等。注意,如果想要拿到e.Result,您需要在BGWorker_DoWork方法中设置 e.Result属性另外,通过RunWorkerCompletedEventArgs实例的Cancelled 属性,以判断是否是Cancel操作使得后台操作终止;
从后台操作返回值
在执行DoWork事件时DoWorkEventArgs实例的Result属性,返回值到用户;在RunWorkerCompleted事件里,RunWorkerCompletedEventArgs 实例的Result属性接收值;
创建BackgroundWorkerDemo例子:
1.新建一个windows窗体应用程序,如:BackgroundWorkerDemo
2.拖一个ProgressBar(进度条)和一个BackgroundWorker控件到Form窗体上,界面如图:

后台代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Threading;
namespace BackgroundWorkerDemo
{
public partial class FrmDemo : Form
{
//设置生成临时文件的路径
static string strSaveDir = @"F:\培训";
public FrmDemo()
{
InitializeComponent();
//显示后台操作的执行进度
this.bgWork.WorkerReportsProgress = true;
//可以取消后台正在执行的操作
this.bgWork.WorkerSupportsCancellation = true;
}
/// <summary>
/// 开始
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Start_Click(object sender, EventArgs e)
{
if (Directory.Exists(strSaveDir) == false)
{
return;
}
btn_Start.Enabled = false;
int count = Convert.ToInt32(this.txt_File.Text.ToString().Trim());
//设置进度条
this.proBar.Minimum = 0;
this.proBar.Maximum = count;
this.proBar.Value = this.proBar.Minimum;
//开始执行异步线程,进行后台操作,给后台传递参数
this.bgWork.RunWorkerAsync(count);
}
/// <summary>
/// 后台操作要处理的任务代码
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bgWork_DoWork(object sender, DoWorkEventArgs e)
{
//获取从RunWorkerAsync()方法里面传递的参数的值
int fileCount= Convert.ToInt32(e.Argument);
Random rand = new Random();
byte[] buffer = new byte[2048];
for (int i = 0; i < fileCount; i++)
{
try
{
string strFileName = Path.Combine(strSaveDir, i.ToString() + ".tmp");
using (var stream = File.Create(strFileName))
{
int n = 0;
int maxByte = 8 * 1024 * 1024;
while (n < maxByte)
{
rand.NextBytes(buffer);
stream.Write(buffer, 0, buffer.Length);
n += buffer.Length;
}
}
}
catch (Exception ex)
{
continue;
}
finally
{
//报告进度
this.bgWork.ReportProgress(i + 1);
Thread.Sleep(100);
}
//判断是否取消了后台操作
if (bgWork.CancellationPending)
{
e.Cancel = true;
return;
}
//设置返回值
e.Result = 234;
}
}
/// <summary>
/// 更新前台界面进度条
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bgWork_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//获取异步任务的进度百分百
int val = e.ProgressPercentage;
this.label2.Text = string.Format("已经生成{0}个文件", val);
//进度条显示当前进度
this.proBar.Value = val;
}
/// <summary>
/// 后台操作完成,向前台反馈信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bgWork_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btn_Start.Enabled = true;
//用户取消操作(e.Cancelled==true,表示异步操作已被取消)
if (e.Cancelled)
{
MessageBox.Show("用户取消后台操作", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("操作完成", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
//接收返回值
int result = (int)e.Result;
MessageBox.Show("返回值:" + result);
}
}
/// <summary>
/// 取消
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Cancle_Click(object sender, EventArgs e)
{
//调用CancelAsync(),取消挂起的后台操作
this.bgWork.CancelAsync();
}
}
}
运行界面:

操作完成界面:

接收返回值:

取消后台操作:

BackgroundWorker控件的更多相关文章
- C#中的BackgroundWorker控件+Delegate.Invoke (委托同步调用)
C#中的BackgroundWorker控件+Delegate.Invoke (委托同步调用) 简单代码,记录一下.一个BackgroundWorker控件 backgroundWorkerRefr ...
- C#窗体的加载等待(BackgroundWorker控件)实现
窗体拉一个Button按钮和一个加载等待显示的label, label默认隐藏,点击按钮时显示这个label,加载完再隐藏 1.工具箱拉BackgroundWorker控件到窗体 2.backgrou ...
- C#中的BackgroundWorker控件
C#中的BackgroundWorker控件 Keywords: C# .NET BackgroundWorkerSource: http://txw1958.cnblogs.com/ Backg ...
- 封装BackgroundWorker控件(提供源代码下载,F5即可见效果)
Demo源码 背景 经常做些小程序或者小DEMO的时候会用到异步,多线程来执行一些比较耗时的工作同时将进度及时进行反馈.我通常会使用位于[ System.ComponentModel]命名空间下的Ba ...
- BackgroundWorker 控件
BackgroundWorker是.net里用来执行多线程任务的控件,它允许编程者在一个单独的线程上执行一些操作.耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 始终处于停 ...
- BackGroundWorker控件的使用注意
该控件有三个事件: DoWork .ProgressChanged 和 RunWorkerCompleted 在程序中调用RunWorkerAsync方法则会启动DoWork事件的事件处理,当在事件处 ...
- 在.Net中进行跨线程的控件操作(下篇:BackgroundWorker)
在.Net中,如果我们在非UI线程上访问窗体上的控件的时候,会产生一个跨线程调用的异常,那么如何处理这种情况呢?在上一章中,我介绍了使用Control.Invoke方法,如果你不习惯使用委托,那么.N ...
- 如何在多线程中调用winform窗体控件
由于 Windows 窗体控件本质上不是线程安全的.因此如果有两个或多个线程适度操作某一控件的状态(set value),则可能会迫使该控件进入一种不一致的状态.还可能出现其他与线程相关的 bug,包 ...
- 实现 winform 异步跨线程访问UI控件
在开发winform时经常会用到多线程防止界面出现假死现象,比如当你单击某个按钮时,需要执行很多代码,但是在执行过程中想实时的将当前执行的情况报告给用户,类型进度条或文本什么的. 这个时候很显然,如果 ...
随机推荐
- LintCode Singleton
Singleton 3 大要素: 1.有private static的句柄(成员变量即field) 2. constructor 必须为private 3.有public static的getInst ...
- HttpSendRequest同步请求不返回
HttpSendRequest是基于socket实现的 在工作过程中发现当发送请求时 1.当网络没有连接时 会同步返回失败 2.当发送请求时 把网线拔下也是会同步返回失败 3.但是第三种情况 发送请求 ...
- hiho一下122周 后缀数组三·重复旋律
后缀数组三·重复旋律3 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列.小Hi ...
- LeetCode 【46. Permutations】
Given a collection of distinct numbers, return all possible permutations. For example,[1,2,3] have t ...
- 20151214下拉列表:DropDownList
注意: .如果用事件的话就要把控件的AutoPostBack设置成true .防止网页刷新用一个判断 if (!IsPostBack)//判断是第一个开始还是取的返回值 { } 下拉列表:DropDo ...
- input:-webkit-autofill 导致chrome的输入框背景颜色变成黄色
填写form表单时发现chrome的一个好坑啊! 当你之前有填写过表单,获取焦点时,input会有一个记录之前填写过的文本的下拉列表式的东东,就像这样:(抱歉丑了点,隐私问题打上了马赛克) 按理说,这 ...
- Angular2.0-组件
截止到目前为止,Angular2.0完成了其alpha-32版本的开发,新的版本还在迭代开发当中,这其中有个问题,就是每个版本相比于以前的版本都会有一些改动,包括API方面的修改,这会导致很多基于以前 ...
- 升级NC6.3
2014-04-23 江苏建工&用友公司会谈提纲 1,合同规定江苏建工用友NC在实施成功之后三年免服务费(2010年增补了资金管理,如果以2010年作为软件最终实施完成,那么2010-2013 ...
- [Tex学习]WinEdit 常用软件快捷键
WinEdit 常用软件快捷键 编辑: Alt+C:在剪贴板原有复制文本后增加新的被选择的文本. Ctrl+Shift+Alt+Right/Left:对选中文本增加或者删除Comment标记. Ctr ...
- delphi 常用的将窗口置前的函数
function BringWindowToTopEx(hWnd: HWND): Boolean;begin if IsIconic(hWnd) then ShowWindow(hWnd, SW_RE ...