當從異步方法返回一個值的時候,此方法體直接返回這個值,但該方法本身被聲明為返回一個Task<TResult>。當聲明一個返回甲類型的方法卻必須返回一個乙類型時,就有點“斷連”了。
// 實際語法public async Task<int> GetValue(){ await TaskEx.Delay(100); return 13; //返回類型是 "int", 而不是"Task<int>"}
問題來了:為什么我不能這么寫?
// 假想語法public async int GetValue(){ await TaskEx.Delay(100); return 13; // 返回類型是 "int"}
// 假想語法public async Task<int> GetValue(){ await TaskEx.Delay(100); async return 13; // "async return" 意味著值被包裝在Task中}
async return關鍵字也被考慮到了,但并沒有足夠的說服力。當把一些同步代碼轉成異步代碼時,這尤其正確。強制人們給每個return語句添加asynchronous就好像是“不必要的忙碌”。比較而言,習慣于“斷連”更容易。
async關鍵字必須用在使用了await關鍵字的方法上。然而,如果把async用在了一個沒有使用await的方法上,也會收到一個警告。
問題:為什么async不能根據await的存在推斷出來?
//假想語法public Task<int> GetValue(){ // "await" 的存在暗示這是一個 "async" 方法. await TaskEx.Delay(100); return 13;}
思考:向后兼容性和代碼可讀性
單字的await關鍵字具有太大的打破變化。在異步方法上的多字await(如await for)或一個關鍵字之間的選擇,只是在那個方法內部啟用await關鍵字。很明顯,使用async標記方法讓人類和計算機分析起來更容易,因此設計團隊決定使用async/await對。
問題:既然顯示包括async有意義(看上面),為什么await不能根據async的存在推斷出來呢?
// 假想語法public async Task<int> GetValue(){ // 暗示有"await",因為這是一個 "async" 方法. TaskEx.Delay(100); return 13;}
思考:異步操作的并行組合。
乍一看,推斷await推斷似乎簡化了基本的異步操作。只要所有的等待可以按序列(如一個操作等待,然后另一個,再然后另一個)完成,這個就能很好的工作。然而,當有人考慮并行組合的時候,它崩潰了。
異步CTP中的并行組合使用TaskEx.WhenAny 和TaskEx.WhenAll方法。這有一個簡單的例子,這個方法立即開始了兩個操作,并且等待它們完成。
// 實際語法public async Task<int> GetValue(){ // 異步檢索兩個部分的值 // 注意此時它們是沒有等待的“not await” Task<int> part1 = GetValuePart1(); Task<int> part2 = GetValuePart2(); // 等待它們的值到達。 await TaskEx.WhenAll(part1, part2); // 計算我們的結果 int value1 = await part1; // 實際上沒有等待 int value2 = await part2; //實際上沒有等待 return value1 + value2;}
為了處理并行組合,我們必須有能力說我們將不會await一個表達式。
新聞熱點
疑難解答