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 中就会将这些误用视为警告,你也可以像上次的文章一样将严重性调为“错误":

4f1829ce858544edf55f5e69822e8c1e.png

同时,分析器也提供了如何纠正的建议: 

b48d5850ea08934152639f372643aa75.gif

结论

今天,我们介绍了 async/await 的常见误用,以及如何纠正。

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值