5 種常見的 async-await 誤用
前言
上次,我們介紹了《如何保證執行異步方法時不會遺漏 await 關鍵字》。
但是,對於 async/await 的誤用不僅於此。
誤用類型
1. 使用不必要的 async/await
有些方法不需要使用 async/await。添加異步修飾符是有代價的:編譯器將在每個異步方法中生成一些代碼。
下列代碼開啓了一個外部 Task,並不需要等待完成:
//修改前
public static async Task Demo()
{
await Task.Factory.StartNew(() => Console.WriteLine("My IO"));
}
//修改後
public static Task Demo()
{
return Task.Factory.StartNew(() => Console.WriteLine("My IO"));
}
2. 異步方法內的長時間運行或阻塞操作
在異步方法中使用一些可能長時間運行或阻塞的操作,即使有這些方法的相應異步版本。
下列代碼使用了ReadToEnd
,而不是對應的異步版本:
//修改前
public static async Task Demo()
{
StreamReader reader = GetReader();
var str = reader.ReadToEnd();
}
//修改後
public static async Task Demo()
{
StreamReader reader = GetReader();
var str = await reader.ReadToEndAsync();
}
3. 異步 void 方法
異步 void 方法中的異常無法在調用方法中捕獲。
下列代碼運行時並不會拋出異常:
//修改前
public static async void Demo()
{
throw new Exception();
await Task.Delay(300);
await Task.Delay(300);
}
//修改後
public static async Task Demo()
{
throw new Exception();
await Task.Delay(300);
await Task.Delay(300);
}
4. 在 using 塊中未 await
在 using 塊內,執行了異步方法但未 await,它可能導致潛在的異常或錯誤的結果。
下列代碼中的CopyToAsync
如果持續時間很長,將拋出 ObjectDisposedException:
//修改前
using (var stream = new FileStream("newfile.txt", FileMode.Open))
{
newStream.CopyToAsync(stream);
}
//修改後
using (var stream = new FileStream("newfile.txt", FileMode.Open))
{
await newStream.CopyToAsync(stream);
}
5. 從嵌套 Task 轉換爲外部 Task
這通常發生在將 async/await 關鍵字與 Task.Factory.StartNew 混用的情況,沒有辦法等待並獲得子任務的結果。
下列代碼中的意圖是進行一秒的延遲,但實際不會有任何延遲:
//修改前
public static async Task Demo()
{
Console.WriteLine("Hello");
await Task.Factory.StartNew(() => Task.Delay(1000));
Console.WriteLine("My IO");
}
//修改後
public static async Task Demo()
{
Console.WriteLine("Hello");
await Task.Run(() => Task.Delay(1000));
Console.WriteLine("My IO");
}
分析器
但是要完全靠人去識別這些錯誤有點難度,這裏介紹一個查找和糾正 async/await 的常見誤用的工具 —— AsyncFixer。
引用 Nuget 包 AsyncFixer 後, 在 VS 中就會將這些誤用視爲警告,你也可以像上次的文章一樣將嚴重性調爲 “錯誤 ":
同時,分析器也提供瞭如何糾正的建議:
結論
今天,我們介紹了 async/await 的常見誤用,以及如何糾正。
想了解更多內容,請關注我的個人公衆號”My IO“
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/MqzrN0fBWY9gJ_1qzPIk-A