基于事件的异步模式——BackgroundWorker

  实现异步处理的方法很多,经常用的有基于委托的方式,今天记录的是基于事件的异步模式。利用BackgroundWorker组件可以很轻松的实现异步处理,并且该组件还支持事件的取消、进度报告等功能。本文以计算两个数X、Y的和为例。

  1. 程序界面如下图,其中三个文本框分别为两个加数和处理结果,两个按钮为计算和取消,按钮下方为进度条。
  2. 引入BackgroundWorker组件,为DoWork、ProgressChanged、RunWorkerCompleted三个事件指定方法。
    将WorkerReportsProgress属性设为true,以支持报告进度。
    将WorkerSupportsCancellation属性设置为true,以支持取消。

    public MainForm()
    {
        InitializeComponent();
        this.backgroundWorker1.DoWork += this.BackgroundWorker1DoWork;
        this.backgroundWorker1.ProgressChanged += this.BackgroundWorker1ProgressChanged;
        this.backgroundWorker1.RunWorkerCompleted += this.BackgroundWorker1RunWorkerCompleted;
        this.backgroundWorker1.WorkerReportsProgress = true;
        this.backgroundWorker1.WorkerSupportsCancellation = true;
        this.buttonCancel.Enabled = false;
    }
  3. 当点击计算按钮时,调用BackgroundWorker的RunWorkerAsync方法实现异步处理,该方法支持一个object类型的参数。这里用元组Tuple<int,int>传递X、Y的值。调用RunWorkerAsync方法,将触发DoWork事件。

    this.backgroundWorker1.RunWorkerAsync(new Tuple<int,int>(Convert.ToInt32(this.textBoxX.Text), Convert.ToInt32(this.textBoxY.Text)));
  4. 当点击取消按钮时,调用BackgroundWorker的CancelAsync方法,这将改变BackgroundWorker的CancellationPending属性的值为false。当执行OnWork方法时可以根据CancellationPending属性,判断用户是否要取消事件。

    this.backgroundWorker1.CancelAsync();   
  5. OnWork方法中可以
    根据CancellationPending属性,判断是否取消。若取消,应在方法结束之前将DoWorkEventArgs的Cancel属性设置为ture。这将用于RunWorkerCompleted事件中判断事件取消还是正常完成。
    通过ReportProgress方法报告进度, 该方法支持一个int类型的参数,该方法将触发ProgressChanged事件。

    void BackgroundWorker1DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        for (int i = 0; i < 10; i++) {
            System.Threading.Thread.Sleep(500);
            if (backgroundWorker1.CancellationPending) {
                e.Cancel = true
                return;
            } else {
                backgroundWorker1.ReportProgress(i * 10);
            }
        }
        var t = e.Argument as Tuple<int,int>;
        e.Result = t.Item1 + t.Item2;
    }
  6. ProgressChanged事件,会将控制权交给UI线程。在其实现方法中根据ProgressChangedEventArgs的ProgressPercentage属性获取进度值。

    void BackgroundWorker1ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
    {
        this.progressBar1.Value = e.ProgressPercentage;
    }
  7. OnWork退出后,将调用RunWorkerCompleted事件。
    根据RunWorkerCompletedEventArgs的Cancelled属性判断是否正常完成。
    根据RunWorkerCompletedEventArgs的Result属性获取处理结果。

    void BackgroundWorker1RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
        this.textBoxResult.Text = e.Cancelled ? "Canceled" : e.Result.ToString();
        this.buttonCancel.Enabled = false;
        this.buttonCalculate.Enabled = true;
        this.progressBar1.Value = 100;
    }
  8. 完整代码

     1 /*
     2  * 由SharpDevelop创建。
     3  * 用户: David Huang
     4  * 日期: 2015/9/8
     5  * 时间: 14:54
     6  */
     7 using System;
     8 using System.Windows.Forms;
     9
    10 namespace BackgroundWorkerTest
    11 {
    12     /// <summary>
    13     /// Description of MainForm.
    14     /// </summary>
    15     public partial class MainForm : Form
    16     {
    17         public MainForm()
    18         {
    19             InitializeComponent();
    20             this.backgroundWorker1.DoWork += this.BackgroundWorker1DoWork;
    21             this.backgroundWorker1.ProgressChanged += this.BackgroundWorker1ProgressChanged;
    22             this.backgroundWorker1.RunWorkerCompleted += this.BackgroundWorker1RunWorkerCompleted;
    23             this.backgroundWorker1.WorkerReportsProgress = true;
    24             this.backgroundWorker1.WorkerSupportsCancellation = true;
    25             this.buttonCancel.Enabled = false;
    26         }
    27         void ButtonCalculateClick(object sender, EventArgs e)
    28         {
    29             this.buttonCalculate.Enabled = false;
    30             this.textBoxResult.Text = string.Empty;
    31             this.buttonCancel.Enabled = true;
    32             this.backgroundWorker1.RunWorkerAsync(new Tuple<int,int>(Convert.ToInt32(this.textBoxX.Text), Convert.ToInt32(this.textBoxY.Text)));
    33         }
    34         void ButtonCancelClick(object sender, EventArgs e)
    35         {
    36             this.backgroundWorker1.CancelAsync();
    37         }
    38         void BackgroundWorker1DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    39         {
    40             for (int i = 0; i < 10; i++) {
    41                 System.Threading.Thread.Sleep(500);
    42                 if (backgroundWorker1.CancellationPending) {
    43                     e.Cancel = true;
    44                     return;
    45                 } else {
    46                     backgroundWorker1.ReportProgress(i * 10);
    47                 }
    48             }
    49             var t = e.Argument as Tuple<int,int>;
    50             e.Result = t.Item1 + t.Item2;
    51         }
    52         void BackgroundWorker1ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
    53         {
    54             this.progressBar1.Value = e.ProgressPercentage;
    55         }
    56         void BackgroundWorker1RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    57         {
    58             this.textBoxResult.Text = e.Cancelled ? "Canceled" : e.Result.ToString();
    59             this.buttonCancel.Enabled = false;
    60             this.buttonCalculate.Enabled = true;
    61             this.progressBar1.Value = 100;
    62         }
    63     }
    64 }

    代码下载:点我

时间: 2024-11-13 00:43:11

基于事件的异步模式——BackgroundWorker的相关文章

MSDN搬运 之 [基于事件的异步模式]

基于事件的异步模式概述 那些同时执行多项任务.但仍能响应用户交互的应用程序通常需要实施一种使用多线程的设计方案.System.Threading 命名空间提供了创建高性能多线程应用程序所必需的所有工具,但要想有效地使用这些工具,需要有丰富的使用多线程软件工程的经验.对于相对简单的多线程应用程序,BackgroundWorker 组件提供了一个简单的解决方案.对于更复杂的异步应用程序,请考虑实现一个符合基于事件的异步模式的类. 基于事件的异步模式具有多线程应用程序的优点,同时隐匿了多线程设计中固有

C#中的异步调用及异步设计模式(三)——基于事件的异步模式

四.基于事件的异步模式(设计层面) 基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合.该异步模式具有以下优点: ·                  “在后台”执行耗时任务(例如下载和数据库操作),但不会中断您的应用程序. ·                  同时执行多个操作,每个操作完成时都会接到通知(在通知中可以区分是完成了哪个操作). ·                  等待资源变得可用,但不会停止(“挂起”)您的应用程序. ·  

基于事件的异步模式(EAP)

什么是EAP异步编程模式 EAP基于事件的异步模式是.net 2.0提出来的,实现了基于事件的异步模式的类将具有一个或者多个以Async为后缀的方法和对应的Completed事件,并且这些类都支持异步方法的取消.进度报告和报告结果.然而.net中并不是所有的类都支持EAP,总结起来有以下17个类支持EAP异步. System.Object的派生类型: System.Activies.WorkflowInvoke System.Deployment.Application.ApplicationD

【温故知新】C#基于事件的异步模式(EAP)

在开发winform和调用asp.net的web service引用的时候,会出现许多命名为 MethodNameAsync 的方法. 例如: winform的按钮点击 this.button1.Click += new System.EventHandler(this.button1_Click); private void button1_Click(object sender, EventArgs e) { //dosomething } 这就是基于事件的异步编程模式,它实现了不影响主线程

异步编程(二)基于事件的异步编程模式 (EAP)

一.引言 在上一个专题中为大家介绍了.NET 1.0中提出来的异步编程模式--APM,虽然APM为我们实现异步编程提供了一定的支持,同时它也存在着一些明显的问题--不支持对异步操作的取消和没有提供对进度报告的功能,对于有界面的应用程序来说,进度报告和取消操作的支持也是必不可少的,既然存在这样的问题,微软当然也应该提供给我们解决问题的方案了,所以微软在.NET 2.0的时候就为我们提供了一个新的异步编程模型,也就是我这个专题中介绍的基于事件的异步编程模型--EAP. 实现了基于事件的异步模式的类将

基于事件的异步编程模式(EAP)

一.引言 在上一个专题中为大家介绍了.NET 1.0中提出来的异步编程模式--APM,虽然APM为我们实现异步编程提供了一定的支持,同时它也存在着一些明显的问题--不支持对异步操作的取消和没有提供对进度报告的功能,对于有界面的应用程序来说,进度报告和取消操作的支持也是必不可少的,既然存在这样的问题,微软当然也应该提供给我们解决问题的方案了,所以微软在.NET 2.0的时候就为我们提供了一个新的异步编程模型,也就是我这个专题中介绍的基于事件的异步编程模型--EAP. 二.介绍 实现了基于事件的异步

BackgroundWorker实现事件的异步模式

最近在看C#的多线程,现把BackgroundWorker实现事件的异步模式这部分用代码注释的形式写出来了,个人理解,有什么不对的还望指正.. namespace LeranTest{ /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { /// <summary> /// 使用BackgroundWorker

实现基于Task的异步模式

返回该系列目录<基于Task的异步模式--全面介绍> 生成方法 编译器生成 在.NET Framework 4.5中,C#编译器实现了TAP.任何标有async关键字的方法都是异步方法,编译器会使用TAP执行必要的转换从而异步地实现方法.这样的方法应该返回Task或者Task<TResult>类型.在后者的案例中,方法体应该返回一个TResult,且编译器将确保通过返回的Task<TResult>是可利用的.相似地,方法体内未经处理的异常会被封送到输出的task,造成返

实践基于Task的异步模式

Await 返回该系列目录<基于Task的异步模式--全面介绍> 在API级别,实现没有阻塞的等待的方法是提供callback(回调函数).对于Tasks来说,这是通过像ContinueWith的方法实现的.基于语言的异步支持通过允许在正常控制流内部等待异步操作隐藏callbacks,具有和编译器生成的代码相同的API级别的支持. 在.Net 4.5,C#直接异步地支持等待的Task和Task<TResult>,在C#中使用"await"关键字.如果等待一个Ta