• BackgroundWorker 类


    在单独的线程上执行操作。
    BackgroundWorker 类允许您在单独的专用线程上运行操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。
    如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。
    若要在后台执行耗时的操作,请创建一个 BackgroundWorker,侦听那些报告操作进度并在操作完成时发出信号的事件。
    可以通过编程方式创建 BackgroundWorker,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。
    如果在 Windows 窗体设计器中创建 BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
    若要设置后台操作,请为 DoWork 事件添加一个事件处理程序。在此事件处理程序中调用耗时的操作。
    若要启动该操作,请调用 RunWorkerAsync。若要收到进度更新通知,请对 ProgressChanged 事件进行处理。
    若要在操作完成时收到通知,请对 RunWorkerCompleted 事件进行处理。
    说明:  
    您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。
    而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
    BackgroundWorker 事件不跨 AppDomain 边界进行封送处理。请不要使用 BackgroundWorker 组件在多个 AppDomain 中执行多线程操作。
     
    如果后台操作需要参数,请在调用 RunWorkerAsync 时给出参数。在 DoWork 事件处理程序内部,可以从 DoWorkEventArgs.Argument 属性中提取该参数。
    请注意:在你调用的后台线程里一定要加上Thread.Sleep(100)这一句,
    别小看这条语句,他使得后台线程运行时可以释放出足够的时间在前台做操作。
    实例如下,首先看界面
    程序实现点击Start按钮在后台线程生成制定数量的GUID,写到listbox中,点击End后停止后台线程。
    1.首先写好函数,此函数我们要在后台运行处理,同事报告进度,还要返回结果
            private int GetDate(BackgroundWorker worker, DoWorkEventArgs e)  
            {  
                //获取传入的参数  
                int maxRecord = (int)e.Argument;  
                int percent = 0;  
                for (int i = 0; i < maxRecord; i++)  
                {  
                    if (worker.CancellationPending)  
                        return i;  
                    percent = (int)((double)i / (double)maxRecord * 100);  
                    //下边这句执行完后激活ProgressChanged事件  
                    worker.ReportProgress(percent, new KeyValuePair<int, string>(i, Guid.NewGuid().ToString()));  
                    //让后台线程Sleep一段时间非常有用,这样前台UI中用户可以做一些其他的输入操作,不至于傻等  
                    Thread.Sleep(100);  
                }  
                return maxRecord;  
            }  
    
    2.设置backgroundWorker1的属性,WorkerReportProgress=true,WorkerSupportsCancellation=true
    3.写DoWork,ProgressChanged,RunWorkerCompleted事件

            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)  
            {  
                try  
                {  
                    BackgroundWorker worker = sender as BackgroundWorker;  
                    e.Result = GetDate(worker, e);  
                }  
                catch (Exception ex)  
                {  
                    MessageBox.Show(ex.Message);  
                    throw;  
                }  
            }  
    

            private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)  
            {  
                KeyValuePair<int, string> record = (KeyValuePair<int, string>)e.UserState;  
                this.label1.Text = string.Format("已经计算了{0}条", record.Key);  
                this.progressBar1.Value = e.ProgressPercentage;  
                this.listBox1.Items.Add(record.Value);  
            }  
    
            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
            {  
                try  
                {  
                    this.label1.Text = string.Format("已经完成,总计{0}", e.Result);  
                    this.btn_start.Enabled = true;  
                    btn_end.Enabled = false;  
                }  
                catch (Exception ex)  
                {  
                    MessageBox.Show(ex.Message);  
                }  
            }  
    

    4.点击Start时的代码

            private void btn_start_Click(object sender, EventArgs e)  
            {  
                if (this.backgroundWorker1.IsBusy)  
                    return;  
                this.listBox1.Items.Clear();  
                this.backgroundWorker1.RunWorkerAsync(100);  
                this.btn_start.Enabled = false;  
                this.btn_end.Enabled = true;  
            }  
    
    点击Start后,this.backgroundWorker1.RunWorkerAsync(100),让Getate生成100个GUID,写入listBox中。
    开始执行DoWork中的代码,同时将参数100封装在DoWorkEventArgs中,通过e.Argument获取,类型是object,需要转换程你需要的类型。
    5.最后写取消事件
            private void btn_end_Click(object sender, EventArgs e)  
            {  
                this.backgroundWorker1.CancelAsync();  
            } 
    

    OK看下运行结果:

    运行时界面可以拖动,不是死锁状态。

  • 相关阅读:
    java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
    JAVA日期处理(Timestamp)
    使用JS截取字符串函数详解
    jQuery获取select option
    JAVA获取oracle中sequences的最后一个值
    <s:iterator> 序号
    Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
    zjoi2018day1 游记
    hihocoder 后缀自动机五·重复旋律8 求循环同构串出现的次数
    hihocoder 1457 后缀自动机四·重复旋律7 求不同子串的和
  • 原文地址:https://www.cnblogs.com/leiOOlei/p/1952011.html
Copyright © 2020-2023  润新知