EasyText, EasyLicense 的作者, https://github.com/EasyHelper Good Good Study,Day Day Up.

 

深入浅出多线程系列之六:事件驱动异步模式(EAP,WebClient,BackgroundWorker)

Event-based asynchronous(EAP)在多线程的环境中提供了一个简单的处理方式。

它有以下几个特性:

 

  1. 支持取消。
  2. 可以安全的更新WPFwindows Forms 控件。
  3. completion event中可以查询异常信息。
  4. “在后台”执行耗时任务(例如下载和数据库操作),但不会中断您的应用程序。

  5. 同时执行多个操作,每个操作完成时都会接到通知。

  6. 等待资源变得可用,但不会停止(“挂起”)您的应用程序。

  7. 使用熟悉的事件和委托模型与挂起的异步操作通信。 

EAP仅仅只是一个模式而已。,所以这些特性必须都由实现者来实现。在Framework中有少数几个类支持这种模式,最著名的就是BackgroundWorkerSystem.Net.WebClient 了。

这个模式的本质是:每个类都提供了一些相似的成员来管理多线程,例如:

 

public byte[] DownloadData(Uri address);

public void DownloadDataAsync(Uri address);

public void DownloadDataAsync(Uri address, object userToken);

public event DownloadDataCompletedEventHandler DownloadDataCompleted;

 

public void CancelAsync(); //取消操作

public bool IsBusy { get; } //获取是否正在运行的信息。

 

下面是使用WebClient 的例子:

var wc = new WebClient();
            wc.DownloadStringCompleted 
+= (sender, args) =>
                {
                    
if (args.Cancelled)
                        Console.WriteLine(
"Canceled");
                    
else if (args.Error != null)
                        Console.WriteLine(
"Exception:" + args.Error.Message);
                    
else
                    {
                        Console.WriteLine(args.Result.Length 
+ " chars were downloaded");
                    }
                };
            wc.DownloadStringAsync(
new Uri("http://www.cnblogs.com/LoveJenny/"));

 

一个WebClient虽然有多个异步方法,但是因为它们都共享了相同的CancelAsync IsBusy属性,所以一次只能有一个异步操作。

 

BackgroundWorker

BackgroundWorkerSystem.ComponentModel下面的一个管理工作线程的帮助类,提供了下面几个特性

  1. 支持取消。
  2. 可以安全的更新WPFwindows Forms 控件。
  3. completion event中可以查询异常信息。
  4. 可以报告进度。
  5. 因为实现了IComponent接口,所以可以被设计器使用。
  6. BackgroundWorker使用了线程池,这意味着你永远都不能在一个BackgroundWorker线程上调用Abort方法
static BackgroundWorker _bw = new BackgroundWorker();

        
public static void MainThread()
        {
            _bw.DoWork 
+= new DoWorkEventHandler(_bw_DoWork);
            _bw.RunWorkerAsync(
"Message to worker");
            Console.ReadLine();
        }

        
static void _bw_DoWork(object sender, DoWorkEventArgs e)
        {
            Console.WriteLine(e.Argument);
            
//做一些耗时的操作。
        }

 

下面的例子实现了进度报告。

class ThreadBackgroundWorker
    {
        
static BackgroundWorker _bw;

        
public static void MainThread()
        {
            _bw 
= new BackgroundWorker
            {
                WorkerReportsProgress 
= true,  //允许报告进度
                WorkerSupportsCancellation = true  //允许取消
            };

            _bw.DoWork 
+= new DoWorkEventHandler(_bw_DoWork);
            _bw.ProgressChanged 
+= new ProgressChangedEventHandler(_bw_ProgressChanged);
            _bw.RunWorkerCompleted 
+= new RunWorkerCompletedEventHandler(_bw_RunWorkerCompleted);

            _bw.RunWorkerAsync(
"Hello to worker");
            Console.WriteLine(
"Press Enter in the next 5 seconds to cancel.");
            Console.ReadLine();
            
            
if (_bw.IsBusy) _bw.CancelAsync();
            Console.ReadLine();
        }

        
static void _bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            
if (e.Cancelled)       //是否取消
                Console.WriteLine("You canceled!");
            
else if (e.Error != null)  //是否有异常
                Console.WriteLine("Worker exception:" + e.Error.ToString());
            
else
                Console.WriteLine(
"Complete:" + e.Result);
        }

        
static void _bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
          
//输出进度报告
            Console.WriteLine("Reached " + e.ProgressPercentage + "%");
        }

        
static void _bw_DoWork(object sender, DoWorkEventArgs e)
        {
            
for (int i = 0; i <= 100; i += 20)
            {
                
if (_bw.CancellationPending) { e.Cancel = truereturn; }
                _bw.ReportProgress(i);   
//报告进度
                Thread.Sleep(1000);
            }

            e.Result 
= 123;
        }
    }

 

 

参考资料:

http://www.albahari.com/threading/

CLR Via C# 3.0

 

posted @ 2011-05-25 22:30  LoveJenny  阅读(4677)  评论(9编辑  收藏  举报
EasyText, EasyLicense 的作者, https://github.com/EasyHelper Good Good Study,Day Day Up.