• 深入浅出多线程系列之六:事件驱动异步模式(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

  • 相关阅读:
    浅谈HTML5单页面架构(一)——requirejs + angular + angular-route
    嵌入式开发之web---vue 前端 注册登录login
    嵌入式开发之web---vue 前端 admin 后台管理系统
    嵌入式开发之web---vue-demo webstorm goahead 嵌入式智能设备
    嵌入式开发之web---vue vscode和vue webstorm 开发环境搭建
    多媒体开发之h264---h264格式说明
    嵌入式开发之内核内存异常排查---关闭oom killer
    Elasticsearch cat api的用法
    Django Mysql SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
    Django-基础-2-ORM
  • 原文地址:https://www.cnblogs.com/LoveJenny/p/2053688.html
Copyright © 2020-2023  润新知