zoukankan      html  css  js  c++  java
  • 基于任务的异步编程模式(TAP)

    异步编程是C#5.0的一个重要改进,提供两个关键字:async和await。使用异步编程,方法的调用是在后台运行(通常在线程或任务的帮助下),但不会阻塞调用线程。异步模式分为3种:异步模式、基于事件的异步模式和基于任务的异步模式(TAP)。TAP是利用关键字async和await实现的,本文将讲解TAP模式。async和await关键字只是编译器的功能。编译器最终会用Task类创建代码。

    1、创建任务

    建立一个同步方法Greeting,该方法在等待一段时间后,返回一个字符串。

     private string Greeting(int delay, string name)
     {
         System.Threading.Thread.Sleep(delay);
         return string.Format("Hello, {0}.", name);
     }

    定义一个方法GreetingAsync,可以使方法异步化,其传入的参数不做强制要求。基于任务的异步模式指定,并返回一个任务。注意,该方法返回的是Task<string>,定义了一个返回字符串的任务,与同步方法返回值一致。

    private Task<string> GreetingAsync(string name, int delay = 3000)
    {
        return Task.Run<string>(() =>
        {
            return Greeting(delay, name);
        });
    }

    2、调用异步方法

    可以使用await关键字调用返回任务的异步方法GreetingAsync。但是,使用await关键字的方法必须要用async关键字修饰符声明。在GreetingAsync方法完成前,被async关键字修饰的方法内await关键字后面的代码不会继续执行。但是,启动被async关键字修饰的方法的线程可以被重用,而没有被阻塞。

    public async void CallerWithAsync()
    {
        string result = await GreetingAsync("Nigel", 2000);
        Console.WriteLine(result);
    }

     注意:async修饰符修饰只能用于返回Task或void的方法。不能作为程序的入口点,即Main方法不能使用async修饰符。await修饰符只能用于返回Task的方法。

    3、延续任务

    GreetingAsync方法返回一个Task<string>对象。该对象包含任务创建的信息,并保存到任务完成。Task类的ContinueWith方法可在任务完成后继续调用的代码。

     public void CallsWithContinuationTask()
     {
         Task<string> task = GreetingAsync("Stephanie", 1000);
         task.ContinueWith(t =>
         {
             Console.WriteLine(t.Result);
         });
     }

    实际上,编译器会把await关键字后的所有代码放进ContinueWith方法内。不论是await关键字的方法还是任务的ContinueWith方法,在方法的不同生命阶段使用了不同的线程。都是当await关键字的方法或任务执行完毕后,再由另一个线程去执行await关键字后面的代码,或给当前线程添加新的任务去执行相关代码。

    在具有UI的应用程序中,应用程序的窗体的控件不允许跨线程访问,需要使用控件的InvokeRequired属性和Invoke方法,将访问UI的方法代码块以委托的形式传递给控件的Invoke,但是在执行前需要判断控件的InvokeRequired。在使用async和await关键字,当await完成后,不需要做任何处理,就可以放访问UI线程(实际上是将控制权又交给了UI线程)。

    4、使用多个异步方法

    4.1、按顺序调用多个异步方法

    使用await关键字可以调用每个异步方法。如果一个异步方法依赖于另一个异步方法,将会起到很大作用。但当异步方法之间没有相互依赖的时候,不使用await关键字将更快返回结果。

     public async void MultipleAsyncMethods()
     {
         DateTime start = DateTime.Now;
         string result1 = await GreetingAsync("Jack",2500);//先执行完它
         string result2 = await GreetingAsync("Tim",1500);//再执行它
         //输出结果
         Console.WriteLine("Finished both methods: MultipleAsyncMethods.
    Result 1: {0}, Result 2: {1}", result1, result2);
         Console.WriteLine("Use time: {0}", (DateTime.Now - start).TotalMilliseconds);
     }

    4.2、使用组合器

    如果任务之间并不依赖于另一个任务,每个异步方法都不需要使用await,而是把每个异步方法的返回结果赋值给Task变量,使用组合器让这些任务并行运行。当组合器内的所有任务都完成后,才会执行后面的代码。

    public async void MultipleAsyncMethodsWithCombinators1()
    {
        DateTime start = DateTime.Now;
        Task<string> t1=  GreetingAsync("Jack", 2500);
        Task<string> t2= GreetingAsync("Tim", 1500);
        await Task.WhenAll(t1, t2);
        //输出结果
        Console.WriteLine("Finished both methods: MultipleAsyncMethodsWithCombinators1.
    Result 1: {0}, Result 2: {1}", t1.Result, t2.Result);
        Console.WriteLine("Use time: {0}", (DateTime.Now - start).TotalMilliseconds);
    }

    如果所有任务类型都返回相同的类型,则可用该类型的数组作为await返回的结果

    public async void MultipleAsyncMethodsWithCombinators2()
    {
        DateTime start = DateTime.Now;
        Task<string> t1 = GreetingAsync("Jack", 2500);
        Task<string> t2 = GreetingAsync("Tim", 1500);
        string[] results= await Task.WhenAll(t1, t2);
        //输出结果
        Console.WriteLine("Finished both methods: MultipleAsyncMethodsWithCombinators2.
    Result 1: {0}, Result 2: {1}", results[0], results[1]);
        Console.WriteLine("Use time: {0}", (DateTime.Now - start).TotalMilliseconds);
    }

     5、异步方法的异常处理

    如果调用异步方法,但是没有等待,那么调用异步方法的线程中使用传统的try/catch块是不能捕获到异步方法中的异常。因为在异步方法执行出现异常之前,已经执行完毕。

    如何捕获异常见《基于任务的异步编程模式(TAP)的错误处理》。

    I travel alone,not to be alone.
  • 相关阅读:
    1014 Waiting in Line (30)(30 point(s))
    1013 Battle Over Cities (25)(25 point(s))
    1012 The Best Rank (25)(25 point(s))
    1011 World Cup Betting (20)(20 point(s))
    1010 Radix (25)(25 point(s))
    1009 Product of Polynomials (25)(25 point(s))
    1008 Elevator (20)(20 point(s))
    1007 Maximum Subsequence Sum (25)(25 point(s))
    1006 Sign In and Sign Out (25)(25 point(s))
    1005 Spell It Right (20)(20 point(s))
  • 原文地址:https://www.cnblogs.com/pilgrim/p/9147313.html
Copyright © 2011-2022 走看看