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)主要属性和事件
这里写图片描述
这里写图片描述

名称 类型 说明 WorkerReportsProgress 属性 获取或设置一个值,该值指示 BackgroundWorker 能否报告进度更新 WorkerSupportsCancellation 属性 获取或设置一个值,该值指示 BackgroundWorker 是否支持异步取消。 IsBusy 属性 获取一个值,指示 BackgroundWorker 是否正在运行异步操作。 CancellationPending 属性 获取一个值,指示应用程序是否已请求取消后台操作。 DoWork 事件 调用 RunWorkerAsync 时发生—-计算 ProgressChanged 事件 调用 ReportProgress 时发生—-与界面交互 RunWorkerCompleted 事件 当后台操作已完成、被取消或引发异常时发生—-完成

(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

0 0
原创粉丝点击