博主簡單數了下,自己曾經發布了約 8 篇關於異步的文章,這次我想單單談下異步的返回類型。
異步方法具有三個可能的返回類型:Task<TResult>、Task和 void。
Task<TResult> 返回類型可用於某種異步方法,其中操作數含有類型 TResult
。
在下面的示例中,GetDateTimeAsync 異步方法包含返回整數的 return 語句。 因此,方法聲明必須指定 Task<int>
。
async Task<DateTime> GetDateTimeAsync() { //Task.FromResult 是一個占位符,類型為 DateTime return await Task.FromResult(DateTime.Now); }
調用 GetDateTimeAsync 方法:
async Task CallAsync() { //在另一個異步方法的調用方式 DateTime now = await GetDateTimeAsync(); }
當 GetDateTimeAsync 從 await 表達式中調用時,await 表達式將檢索存儲在由 GetDateTimeAsync 返回的任務中的 DateTime 類型值。
async Task CallAsync() { //在另一個異步方法的調用方式 //DateTime now = await GetDateTimeAsync(); //換種方式調用 Task<DateTime> t = GetDateTimeAsync(); DateTime now = await t; }
通過 CallAsync 方法對 GetDateTimeAsync 方法的調用。 對非立即等待的方法 GetDateTimeAsync 的調用返回 Task<DateTime>
,正如你從方法聲明預料的一樣。 該任務指派給示例中的 DateTime 的 Task
變量。 因為 DateTime 的 Task
變量是 Task<DateTime>,所以它屬於包含類型 TResult
的 DateTime 屬性。 在這種情況下,TResult 表示日期類型。 當 await
應用於 Task<DateTime>,await 表達式的計算結果為 Task<DateTime> 的 DateTime 屬性內容。 該值會分配給 now 變量。
這次我演示不同的變量,你可以自己對比下結果是否相同:
async Task CallAsync() { //在另一個異步方法的調用方式 DateTime now = await GetDateTimeAsync(); //換種方式調用 Task<DateTime> t = GetDateTimeAsync(); DateTime now2 = await t;
//輸出的結果對比 Console.WriteLine($"now: {now}"); Console.WriteLine($"now2: {now2}"); Console.WriteLine($"t.Result: {t.Result}"); }
【注意】Result 屬性為鎖定屬性。 如果你在其任務完成之前嘗試訪問它,當前處於活動狀態的線程將被阻止,直到任務完成且值為可用。 在大多數情況下,應通過使用 await
訪問此值,而不是直接訪問屬性。
不包含 return 語句或包含不返回操作數的 return 語句的異步方法通常具有返回類型 Task。 如果被編寫為異步運行,這些方法將為返回 void 的方法。 如果在異步方法中使用 Task
返回類型,調用方法可以使用 await 運算符暫停調用方的完成,直至被調用的異步方法結束。
請看示例:
async Task DelayAsync() { //Task.Delay 是一個占位符,用於假設方法正處於工作狀態。 await Task.Delay(100); Console.WriteLine("OK!"); }
通過使用 await 語句而不是 await 表達式來調用和等待 DelayAsync 方法,類似於返回 void 的方法的調用語句。 await 運算符的應用程序在這種情況下不生成值。
請看調用 DelayAsync 的示例。
//調用和等待方法在同一聲明中 await DelayAsync();
現在,我用將調用和等待的方法進行分離:
//分離 Task delayTask = DelayAsync(); await delayTask;
void 返回類型主要用在事件處理程序中,其中需要 void 返回類型。 void 返回類型還可用於替代返回 void 的方法,或者用於執行可分類為"調用後不管了"活動的方法。 但是,你應盡可能地返回 Task
,因為不能 await 返回 void 的異步方法。 這種方法的任何調用方只能夠繼續完成,而無需等待調用的異步方法完成,並且調用方必須獨立於異步方法生成的任何值或異常。
返回 void 的異步方法的調用方無法捕獲從該方法引發的異常,且此類未經處理的異常可能會導致應用程序故障。 如果返回 Task 或 Task<TResult> 的異步方法中出現異常,此異常將存儲於返回的任務中,並在等待該任務時再次引發。 因此,請確保可以產生異常的任何異步方法都具有返回類型 Task 或 Task<TResult>,並確保會等待對這些方法的調用。
現在,異常也可以使用 await 了,請移步到這裡 《回眸 C# 的前世今生 - 見證 C# 6.0 的新語法特性》。
void 返回值示例:
private async void button1_Click(object sender, EventArgs e) { //啟動進程並等待完成 await Task.Delay(100); }
【博主】反骨仔
【出處】http://www.cnblogs.com/liqingwen/p/6218994.html
【參考】微軟官方文檔