C#基礎回顧Async 的回傳類型

黄舟
發布: 2017-02-07 15:08:48
原創
1879 人瀏覽過


部落客簡單數了下自己發佈過的非同步文章,已經斷斷續續 8 篇了,這次我想以 async 的回傳類型為例,單獨談談。

非同步方法有三個可能的回傳類型:Task、Task 和 void。 

什麼時候需要使用哪一種回傳類型,具體情況需要具體分析。如果使用不當,程式的執行結果也許不是你想要的,下面我們就來好好談談如何針對不同的情況選擇不同的返回類型。

Task 

【記住】當你加入 async 關鍵字後,需要傳回一個將用於後續操作的對象,請使用 Task

Task 傳回類型可用於某種非同步方法,其中運算元含有類型 TResult。

在下面的範例中,GetDateTimeAsync 非同步方法包含一個傳回目前時間的 return 語句。 因此,方法宣告必須指定 Task

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 的 Task 變數。 因為 DateTime 的 Task 變數是 Task,所以它屬於包含類型 TResult 的 DateTime 屬性。 在這種情況下,TResult 表示日期類型。 當 await 應用於 Task,await 表達式的計算結果為 Task 的 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 來存取屬性值,而不是直接存取屬性。

Task

不包含 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 傳回型別也可用於取代傳回 void 的方法,或是用於執行可分類為"呼叫後不管了"活動的方法。 但是,你應盡可能地回傳 Task,因為不能 await 回傳 void 的非同步方法。 這種方法的任何呼叫方只能夠繼續完成,而無需等待呼叫的非同步方法完成,且呼叫方必須獨立於非同步方法產生的任何值或異常。

傳回 void 的非同步方法的呼叫方無法捕獲從該方法引發的異常,且此類未經處理的異常可能會導致應用程式故障。 如果傳回 Task 或 Task 的非同步方法中出現異常,此異常將儲存於傳回的任務中,並在等待該任務時再次引發。 因此,請確保可以產生異常的任何非同步方法都具有傳回類型 Task 或 Task,並確保會等待這些方法的呼叫。

現在,異常也可以使用 await 了,請移步到這裡 《回眸 C# 的前世今生 - 見證 C# 6.0 的新語法特性》。

void 回傳值範例:

private async void button1_Click(object sender, EventArgs e)
{
    //启动进程并等待完成
    await Task.Delay(100);
}
登入後複製

以上就是C#基礎回顧Async 的回傳類型的內容,更多相關內容請關注PHP中文網(www.php.cn)!


相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!