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