BackgroundWoker
来源:互联网 发布:c语言判断水仙花数 编辑:程序博客网 时间:2024/06/10 00:01
1.引言
在Winform中,UI线程里面涉及到大量的计算从而导致界面假死状态怎么办?多线程呗,多线程怎么组织?界面怎么响应?工作线程和UI线程怎么交互?BackgroundWoker组件应运而生。
2.BackgroundWoker
(1)版本:此类在 .NET Framework 2.0 版中是新增的。
(2)命名空间:System.ComponentModel;
(3)解决问题:允许您在单独的专用线程上运行操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。
(4)创建:若要在后台执行耗时的操作,请创建一个 BackgroundWorker,侦听那些报告操作进度并在操作完成时发出信号的事件。可以通过编程方式创建 BackgroundWorker,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。如果在 Windows 窗体设计器中创建 BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
注意事项:
您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。BackgroundWorker事件不跨 AppDomain边界进行封送处理。请不要使用BackgroundWorker 组件在多个 AppDomain 中执行多线程操作。
3.示例
public partial class FrnBackgroudWokerTest : Office2007Form { public FrnBackgroudWokerTest() { InitializeComponent(); this.EnableGlass = false; CheckForIllegalCrossThreadCalls = false; } private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { if (e.Argument == null) e.Cancel = true; BackgroundWorker bgWoker = sender as BackgroundWorker; int max = Convert.ToInt32(e.Argument); for (int i = 1; i <= max; i++) { if(!bgWoker.CancellationPending) { Thread.Sleep(20); int percentage = Convert.ToInt32(Math.Floor((Convert.ToDouble(i) / max) * 100)); bgWoker.ReportProgress(percentage, i); manualReset.WaitOne(); } else { e.Cancel = true; } } e.Result = "处理完毕!"; } private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { SetProgressBarAndTxtStatus(e.ProgressPercentage, Convert.ToInt32(e.UserState)); } private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if(e.Cancelled) { MessageBoxEx.Show("操作取消!"); return; } if (e.Result == null || string.IsNullOrEmpty(e.Result.ToString())) { MessageBoxEx.Show("处理错误!"); } else { MessageBoxEx.Show(e.Result.ToString()); } } private void btnOK_Click(object sender, EventArgs e) { if(!this.backgroundWorker.IsBusy) { this.backgroundWorker.RunWorkerAsync(1000); } } private ManualResetEvent manualReset = new ManualResetEvent(true); private void btnPause_Click(object sender, EventArgs e) { if (btnPause.Text == "暂停") { manualReset.Reset();//暂停当前线程的工作,发信号给waitOne方法,阻塞 btnPause.Text = "继续"; } else { manualReset.Set();//继续某个线程的工作 btnPause.Text = "暂停"; } } private void btnCancel_Click(object sender, EventArgs e) { this.backgroundWorker.CancelAsync(); } private string GetProgressBarStr(int value) { return string.Format("{0}%", value); } private void SetProgressBarAndTxtStatus(int progressPercentage, int userState) { this.progressBar.Text = GetProgressBarStr(progressPercentage); this.txtCurrentValue.Text = userState.ToString(); this.progressBar.Value = userState; }
运行结果(确定):
运行结果(暂停):
运行结果(取消):
4.说明
(1)主要属性和事件
(2)注意事项
(A)如果要报告进度和支持异步取消,那么WorkerReportsProgress 和WorkerSupportsCancellation 应该设置为true。
(B)调用代码之前先确认异步线程不是在运行,像上面代码一样if(!this.backgroundWorker.IsBusy)。
(C)取消异步线程if(!bgWoker.CancellationPending),需要一个指示器,否则单独调用this.backgroundWorker.CancelAsync()不管用。
(3)参数传递
(A)this.backgroundWorker.RunWorkerAsync(1000)启动异步线程参数Object类型,可以从backgroundWorker_DoWork的事件信息对象e.Argument去获取。
(B)bgWoker.ReportProgress(percentage, i),报告进度参数在响应事件中通过backgroundWorker_ProgressChanged的信息对像e.ProgressPercentage和e.UserState来获取。
(C)如果后台计算完毕(DoWork执行完毕)有返回结果,把这个结果传递给RunWorkerCompleted,应该先将结果赋值给DoWork的信息对象e.Result,然后通过RunWorkerCompleted的信息对象e.Result取出即可。
(4)关于ManualResetEvent
参考:线程同步:ManualResetEvent和AutoResetEvent
- BackgroundWoker
- c# .net ProgressBar BackGroundWoker 连接数据库的进度显示
- Android init.rc文件浅析
- linux定时任务的设置
- KVM虚拟化技术之使用Qemu-kvm创建和管理虚拟机
- easyui datagrid 编辑行绑定combogrid并实现下拉赋值
- 为了保护您的计算机 将不打开此文件
- BackgroundWoker
- 大数据学习笔记-------------------(22)
- To be a runner, not a loser----2016南马记
- 下载编译安装Apache HTTP Server 2.4.23以及配置HTTP/HTTPS反向代理
- SQL语句获取数据库中的 表主键,自增列,所有列,其他有用的SQL
- 算法库algorithm-3-gather
- php三种接口(json、XML、jsonp)的生成与调
- java 判断返回类型是非为空(null 与 a.length()的区别)
- QT下int与QByteArray的转换