backgroundworker
在 WinForms 或WPF中,有时要执行耗时的操作,在该操作未完成之前操作用户界面,会导致用户界面停止响应。
解决的方法就是新开一个线程,把耗时的操作放到线程中执行,这样就可以在用户界面上进行其它操作。
新建线程可以用 Thread 类,可以实现多线程同时操作,简单的可以通过 BackgroundWorker 类实现。
用 BackgroundWorker 类执行耗时的操作
BackgroundWorker 类在 System.componentModel 命名空间下。
VS 的工具箱时有一个 BackgroundWorker 组件,就是这个类。
---------------------------------------------------------------------------------------------------------------------------------------
选择用async/await特性,还是用BackgroundWorker类:
async/await更适合那些需要在后台完成的不相关的小任务,默默开始,默默结束。
BackgroundWorker适合在后台工作的同时要跟主线程通信的情况,如实时反馈工作进度,允许用户中途中断这个任务,任务完成后的回调等等。
---------------------------------------------------------------------------------------------------------------------------------------
常用方法
1.RunWorkerAsync
开始执行后台操作。引发 DoWork 事件
2.CancelAsync
请求取消挂起的后台操作。
注意:这个方法是将 cancellationPending 属性设置为 true,并不会终止后台操作。在后台操作中要检查 CancellationPending 属性,来决定是否要继续执行耗时的操作。
3.Reportprogress
引发 ProgressChanged 事件。
常用属性
1.CancellationPending
指示应用程序是否已请求取消后台操作。
只读属性,默认为 false,当执行了 CancelAsync 方法后,值为 true。
2.WorkerSupportsCancellation
指示是否支持异步取消。要执行 CancelAsync 方法,需要先设置该属性为 true。
3.WorkerReportsProgress
指示是否能报告进度。要执行 ReportProgress 方法,需要先设置该属性为 true。
常用事件
1.DoWork
调用 RunWorkerAsync 方法时发生。
2.RunWorkerCompleted
后台操作已完成、被取消或引发异常时发生。
3.ProgressChanged
调用 ReportProgress 方法时发生。
在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
如果想在 DoWork 事件处理程序中和用户界面的控件通信,可在用 ReportProgress 方法。
ReportProgress(int percentProgress, object userState),可以传递一个对象。
ProgressChanged 事件可以从参数 ProgressChangedEventArgs 类的 UserState 属性得到这个信息对象。
简单的程序用 BackgroundWorker 比 Thread 方便,Thread 中和用户界面上的控件通信比较麻烦,需要用委托来调用控件的 Invoke 或 begininvoke 方法,没有 BackgroundWorker 方便。
实例:
界面
代码:
public partial class Form1 : Form
{
//设置生成临时文件的路径
static string strSaveDir = @"C:\培训";
public Form1()
{
InitializeComponent();
//显示后台操作的执行进度
this.bgWork.WorkerReportsProgress = true;
//可以取消后台正在执行的操作
this.bgWork.WorkerSupportsCancellation = true;
}
private void Form1_Load(object sender, EventArgs e)
{
bgWork.DoWork += bgWork_DoWork;
bgWork.ProgressChanged += bgWork_ProgressChanged;
bgWork.RunWorkerCompleted += bgWork_RunWorkerCompleted;
}
/// <summary>
/// 更新前台界面进度条
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void bgWork_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//获取异步任务的进度百分百
int val = e.ProgressPercentage;
this.label2.Text = string.format("已经生成{0}个文件", val);
//进度条显示当前进度
this.progressBarControl1.EditValue = val;
}
/// <summary>
/// 后台操作要处理的任务代码
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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>
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);
}
}
private void btn_Start_Click(object sender, EventArgs e)
{
if (!directory.exists(strSaveDir))
{
directory.createdirectory(strSaveDir);
}
btn_Start.Enabled = false;
int count = Convert.ToInt32(this.txt_File.Text.ToString().Trim());
//设置进度条
this.progressBarControl1.Properties.Minimum = 0;
this.progressBarControl1.Properties.Maximum = count;
//开始执行异步线程,进行后台操作,给后台传递参数
this.bgWork.RunWorkerAsync(count);
}
private void btn_Cancel_Click(object sender, EventArgs e)
{
//调用CancelAsync(),取消挂起的后台操作
this.bgWork.CancelAsync();
}
}
相关阅读
在使用win 7 无线承载网络时,启动该服务时,有时会提示:组或资源的状态不是执行请求操作的正确状态。网上有文章指出,解决这个问题的方
问题:操作数类型冲突: uniqueidentifier 与 int 不兼容
重点内容 操作数类型冲突: uniqueidentifier 与 int 不兼容! 这是遇到的问题
一、 录制脚本1.安装完毕后,创建脚本:点击OK之后,会弹出网址,之后创建Action,每进一个页面添加一个Action,录制结束后,终止录制。二、
整理自廖雪峰的git教程1.创建git项目 git init 添加文件 git add XXXXXXXXXXX.py 提交申请 为什么Git添加文件需要add,commit一
C#操作xml文件:使用XmlDocument 实现读取和写入
XML文件是一种常用的文件格式,例如WinForm里面的app.config以及Web程序中的web.config文件,还有许多重要的场所都有它的身影。Xml是