美文网首页
异步编程(四):async/await模式之await表达式

异步编程(四):async/await模式之await表达式

作者: 曦航老袁 | 来源:发表于2019-02-24 12:06 被阅读0次

    await表达式作用是指定异步执行的任务,由await关键字和一个空闲对象(简称任务)组成。这个任务可能是一个Task类型的对象,也可能不是。默认状态下,这个任务是在当前线程异步执行的。

    await task
    

    任务是一个awaitable类型的对象。awaitable类型是指包含GetAwaiter方法的类型,该方法没有参数,返回一个称为awaiter类型的对象。awaiter类型包括以下成员:

    • bool IsCompleted{ get; }
    • void OnCompleted{ Action };
    • void GetResult(); 或者 T GetResult();

    在实际使用过程中,大多数时候你并不需要构建自己的awaitable。你只需要使用Task类型就足够了。
    在.NET 4.5中,微软发布了大量新的和修订的异步方法(在BCL中),它们可以返回Task<T>类型的对象。将它们放置到await语句中,就可以在当前线程中异步执行。

    Uri site = new Uri(“http://www.baidu.com”);
    WebClient wc = new WebClient();
    string value = await wc.DownLoadStringTaskAsync(site);
    

    但更多时候我们还是需要构建自己方法,做为await表达式的任务。最简单的方式是使用Task.Run方法。有一点需要特别注意:它是在不同的线程上运行你的方法!

    例如:Task.Run( Func<TResult> func)

    可以看出,你的方法传递需要基于该方法创建一个委托。下面将用一段代码显示通常使用的三种方式:

    class MyClass
    {
        public int Get10()
        {
            return 10;
        }
    
        public async Task DoWorkAsync()
        {
            Func<int> ten = new Func<int>(Get10);
            int a = await Task.Run( ten );
            int b = await Task.Run( new Func<int>(Get10);
            int c = await Task.Run(() => { return 10; });
            Console.WriteLine( “{0}    {1}    {2}”, a, b, c);
        }
    }
    
    class Program
    {
        static void Main()
        {
            Task t = (new MyClass()).DoWorkAsync();
            t.Wait();
        }
    }
    

    上面的示例中我们使用的Task.Run的签名以Func<TResult>为参数,才方法共有8个重载:

    返回类型 签名
    Task Run( Action action)
    Task Run( Action action, CancellationToken token )
    Task<TResult> Run( Func<TResult> function)
    Task<TResult> Run( Func<TResult> function, CancellationToken token )
    Task Run( Func<TResult> function)
    Task Run( Func<TResult> function, CancellationToken token )
    Task<TResult> Run( Func<TResult> function)
    Task<TResult> Run( Func<TResult> function, CancellationToken token )

    可以作为Task.Run方法第一个参数的委托类型包括:

    委托类型 签名 含义
    Action void Action() 无参数且无返回值的方法
    Func<TResult> TResult Func() 无参数但有返回值的方法
    Func<Task> Task Func() 无参数返回简单Task对象的方法
    Func<Task<TResult>> Task<TReslut> Func() 无参数返回Task<T>类型对象的方法

    下面举一个例子展示4个不同的await语句:

    static class MyClass
    {
        public static async Task DoWorkAsync()
        {
            await Task.Run(() => Console.WriteLine(5.ToString()));
    
            Console.WriteLine((await Task.Run(() => 6)).ToString());
    
            await Task.Run(() => Task.Run(() => Console.WriteLine(7.ToString())));
    
            int value = await Task.Run(() => Task.Run(() => 8));
            Console.WriteLine(value.ToString());
        }
    }
    
    class Program
    {
        static void Main()
        {
            Task t = MyClass.DoWorkAsync();
            t.Wait();
            Console.WriteLine("Press Enter key to exit.");
            Console.Read();
        }
    }
    

    代码运行结果:

    5
    6
    7
    8
    

    在能使用任何表达式的地方,都可以使用await表达式(当然要位于异步方法内)。上述的语句中,第一个和第三个实例将await表达式用作语句;第二个实例将await表达式用作WriterLine方法的参数;第四个实例将await表达式用作赋值语句的右端。
    假设我们的某个方法不符合这四种委托形式。例如有一个GetSum方法以两个int值作为参数输入,并返回这两个值的和。这与上述四种可接受的委托均不兼容。解决方案是用可以接受的Fun委托形式创建一个Lambda方法。代码如下:

    int value = await Task.Run(()=>GetSum(5,6));
    Console.WriteLin(value.tostring);
    

    相关文章

      网友评论

          本文标题:异步编程(四):async/await模式之await表达式

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