C# 從基礎到精通 — 第 8 講
使用async和await建立非同步任務
該部落格上撰寫的文章是出於教學目的而創建的。 另外,文章中的資訊可能不正確,請謹慎。
在等待網路或檔案操作時阻塞執行緒也可能凍結螢幕和其他操作。 async 和await 表示等待任務,以便可以連續執行。
返回任務
async Task<PlayerData> LoadPlayerAsync(
string url,
CancellationToken cancellationToken)
{
using HttpResponseMessage response =
await httpClient.GetAsync(url, cancellationToken);
response.EnsureSuccessStatusCode();
PlayerData? data = await response.Content
.ReadFromJsonAsync<PlayerData>(cancellationToken);
return data ?? throw new InvalidDataException("Player data is empty");
}
當您遇到等待時,您可以稍後繼續執行其餘程式碼,而不是保留當前執行緒直到任務完成。 非同步方法基本上會傳回一個任務,以便呼叫者可以觀察完成和失敗。
取消轉發
using var source = new CancellationTokenSource(TimeSpan.FromSeconds(5));
try
{
PlayerData data = await LoadPlayerAsync(url, source.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Loading canceled");
}
Cancel 不是強制終止執行緒的函數。 請求任務驗證令牌並在安全點中止的合約。
等待多個任務
Task<ItemData> itemTask = LoadItemsAsync(token);
Task<QuestData> questTask = LoadQuestsAsync(token);
await Task.WhenAll(itemTask, questTask);
ItemData items = await itemTask;
QuestData quests = await questTask;
相互不依賴的等待任務可以先啟動,然後一起等待。 簡單地將 CPU 計算標記為非同步並不會自動使其並行計算。
避免流動
使用Task的.Result或.Wait()進行同步等待可能會阻塞執行緒或建立死鎖,具體取決於執行環境。 最好盡可能繼續異步呼叫路徑。
除事件處理程序外,應避免使用 async void,因為呼叫者無法等待完成和異常。 非同步程式碼的關鍵不是添加關鍵字,而是向呼叫者傳達完成、失敗和取消的流程。