15.3 Task 语法和语义

15.3.1 声明异步方法和返回类型

1         async static void GetStringAsync()
2         {
3             using (var client = new HttpClient())
4             {
5                 Task<string> task = client.GetStringAsync("https://www.baidu.com/");
6                 string result = await task;
7             }
8         }

15.3.3 可等待模式

  大量工作都是通过模式来表示的,这有点类似于 foreach 和LINQ查询。为了更清晰地描述
该模式的轮廓,假设存在一些相关的接口(但实际并没有)。稍后我会介绍真实情况,现在先来
看看虚构的接口:

 1     /// <summary> 为包含返回值的异步操作 建立的虚拟的接口  警告:这些并不存在 自定义的</summary>
 2     public interface IAwaitable<T>
 3     {
 4         IAwaiter<T> GetAwaiter();
 5     }
 6 
 7     public interface IAwaiter<T> : INotifyCompletion
 8     {
 9         bool IsCompleted { get; }
10         T GetResult();
11 
12         //从INotifyCompletion 继承
13         //void OnCompleted(Action continuation);
14     }
15 
16     /// <summary> 为没有返回值的异步操作 建立的虚拟的接口 </summary>
17     public interface IAwaitable
18     {
19         IAwaiter GEtAwaiter();
20     }
21 
22     public interface IAwaiter : INotifyCompletion
23     {
24         bool IsCompleted { get; }
25         void GetResult();
26 
27         //从INotifyCompletion 继承
28         //void OnCompleted(Action continuation);
29     }

  前面讲述了什么样的表达式可以作为 await 关键字的目标,不过整个表达式本身也同样拥有
一个有趣的类型:如果 GetResult() 返回 void ,那么整个 await 表达式就没有类型,而只是一
个独立的语句。否则,其类型与 GetResult() 的返回类型相同。
  例如, Task<TResult>.GetAwaiter() 返回一个 TaskAwaiter<TResult> ,其 GetResult()
方法返回 TResult 。(希望你不会感到奇怪。)根据 await 表达式的类型规则,我们可以编写这样
的代码:

1             using (var client = new HttpClient())
2             {
3                 Task<string> task = client.GetStringAsync("https://www.baidu.com/");
4                 string result = await task;
5             }

  这里的 await 表达式不会返回任何类型的值,因此不能将其分配给变量,或作为方法实参进
行传递,也不能执行其他任何将表达式作为值的相关操作。
  需要注意的是,由于 Task 和 Task<TResult> 都实现了可等待模式,因此可以在一个异步方
法内调用另一个异步方法:

 1         public async Task<int> Foo()
 2         {
 3             string bar = await BarAsync();
 4             //显然通常会更复杂
 5             return bar.Length;
 6         }
 7         public async Task<string > BarAsync()
 8         {
 9             //一些异步代码,可能会调用更多异步方法
10         }

  组合异步操作正是异步特性大放异彩的一个方面。进入异步模式(mode)后,就可以很轻
松地保持这种模式,编写自然流畅的代码。

 

posted @ 2018-12-15 20:24  一只桔子2233  阅读(215)  评论(0编辑  收藏  举报