美文网首页.NET多线程
.NET多线程(五)异步操作

.NET多线程(五)异步操作

作者: 万州大牛 | 来源:发表于2017-03-12 19:31 被阅读0次

    5、异步操作

    5.1 异步操作基础

    异步操作发展历史,APM模式,EAP模式,TPL模式

    .NET 1.0

    System.Threading.Thread
    适用耗时操作、特殊操作、低优先级操作,默认前台

    System.Threading.ThreadPool
    适合短时操作,线程池线程默认后台

    # APM 异步操作模式
    

    .NET 2.0

    Thread 构造支持 ParameterizedThreadStart 传参数

    匿名方法 delegate,闭包

    ParameterizedThreadStart start = delegate(object obj) { };
    

    同步上下文 SynchronizationContext
    主要用在桌面UI应用 Send(同步) or Post(异步)

    # EAP 异步操作模式
    

    .NET 3.5

    拉姆达表达式

    泛型委托 Action 无返回结果,Func 最后必须结果

    Action a1 = new Action(() => { });
    Action<string> a2 = new Action<string>((s) => { });
    Func<string> f1 = new Func<string>(() => { return ""; });
    Func<int, string> f2 = new Func<int, string>((n) => { return n.ToString(); });
    

    .NET 4.0

    线程池线程最大数量,是根据电脑内存来计算的

    优化线程池工作项排序
    在 .net 4.0 以前,线程池的工作项,采用链表排队
    现在CPU都是多核处理器,假设现在有很多工作项
    出现的问题:
    (1)链表结构会存在很多引用,对垃圾回收影响很大
    (2)链表是按顺序操作,多核CPU真正的并发受到影响
    在 .net 4.0 重新设计工作项排队结构
    数组+链表
    数组元素对应工作项引用
    (1)引用减少了
    (2)现在是操作数组元素

    # TPL 异步操作模式
    

    5.2 异步操作模式

    (1)APM 模式 Asynchronous Programming Model

    2个方法 Begin/End,1个 IAsyncResult

    必须调用 End,即使不需要返回结果,因为 End 会把线程的异常抛出来
    调用 End 加 try/catch
    调用 Begin 之后,应当避免直接调用 End,因为 End 会等待结果,可能无限等待

    APM 获取结果

    (1)轮询是否完成

    主要使用 System.Windows.Forms.Timer
    轮询 IAsyncResult 的 IsCompleted,并调用 End 获取结果

    (2)等待完成,IAsyncResult 的 AsyncWaitHandle 可以设置超时

    直接调用 End,可能因为线程死锁等,无限等待
    使用 AsyncWaitHandle 可以设置超时,但是超时了就不会调用 End
    不调用 End 就意味着线程的,异常可能没捕获,资源可能泄露
    所以 AsyncWaitHandle 并不完美

    (3)完成时回调,AsyncCallback

    这里有个问题,就是回调并不是在UI线程,如果要更新UI控件,那就不可以

    static void Main(string[] args)
    {
        HelloDelegate helloDelegate = new HelloDelegate(Hello);
        helloDelegate.BeginInvoke(Callback, helloDelegate);
        Console.ReadLine();
    }
    static void Callback(IAsyncResult ar)
    {
        HelloDelegate helloDelegate = ar.AsyncState as HelloDelegate;
        try
        {
            string s = helloDelegate.EndInvoke(ar);
            Console.WriteLine(s);
        }
        catch (Exception) { }
    }
    static string Hello()
    {
        return "hello";
    }
    public delegate string HelloDelegate();
    

    APM 其他事

    .NET 框架的一些类已经实现了 APM 模式
    例如:使用 I/O thread 的 WebRequest,Stream,Socket,SqlCommand,MessageQueue 等

    委托内在支持 APM 模式,使用(worker thread)

    (2)EAP 模式 Event-Based Asynchronous Pattern

    1个异步Async方法,1个Completed事件

    static void Main(string[] args)
    {
        WebClient webClient = new WebClient();
        webClient.DownloadDataCompleted += delegate(object sender, DownloadDataCompletedEventArgs e)
        {
            try
            {
                byte[] result = e.Result;
            }
            catch (Exception) { }
        };
        webClient.DownloadDataAsync(new Uri(""));
    }
    

    在获取 Result 的时候, try/catch
    EAP 有个问题,如果发起多个异步请求,在完成事件里,需要区分结果来自哪个异步操作呢

    (3)TPL 模式 Task Parallel Library

    基于 System.Threading.Tasks.Task
    实现标准的取消线程,报告线程进度操作

    Task 本质代表未来的操作

    Task task = new Task(() =>
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        throw new Exception("error");
    });
    task.Start();
    task.ContinueWith((t) =>
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        Console.WriteLine(t.Exception.InnerException.Message);
    }, TaskContinuationOptions.OnlyOnFaulted);
    Console.ReadLine();
    

    相关文章

      网友评论

        本文标题:.NET多线程(五)异步操作

        本文链接:https://www.haomeiwen.com/subject/tkjgbttx.html