• 5 种常见的 async/await 误用


    前言

    上次,我们介绍了《如何保证执行异步方法时不会遗漏 await 关键字》。

    但是,对于async/await 的误用不仅于此。

    误用类型

    1.使用不必要的 async/await

    有些方法不需要使用async/await。添加异步修饰符是有代价的:编译器将在每个异步方法中生成一些代码。

    下列代码开启了一个外部 Task,并不需要等待完成:

    1. //修改前
    2. public static async Task Demo()
    3. {
    4.     await Task.Factory.StartNew(() => Console.WriteLine("My IO"));
    5. }
    6. //修改后
    7. public static Task Demo()
    8. {
    9.     return Task.Factory.StartNew(() => Console.WriteLine("My IO"));
    10. }

    2.异步方法内的长时间运行或阻塞操作

    在异步方法中使用一些可能长时间运行或阻塞的操作,即使有这些方法的相应异步版本。

    下列代码使用了ReadToEnd,而不是对应的异步版本:

    1. //修改前
    2. public static async Task Demo()
    3. {
    4.     StreamReader reader = GetReader();
    5.     var str = reader.ReadToEnd();
    6. }
    7. //修改后
    8. public static async Task Demo()
    9. {
    10.     StreamReader reader = GetReader();
    11.     var str = await reader.ReadToEndAsync();
    12. }

    3.异步 void 方法

    异步 void 方法中的异常无法在调用方法中捕获。

    下列代码运行时并不会抛出异常:

    1. //修改前
    2. public static async void Demo()
    3. {
    4.     throw new Exception();
    5.     await Task.Delay(300);
    6.     await Task.Delay(300);
    7. }
    8. //修改后
    9. public static async Task Demo()
    10. {
    11.     throw new Exception();
    12.     await Task.Delay(300);
    13.     await Task.Delay(300);
    14. }

    4.在 using 块中未 await

    在 using 块内,执行了异步方法但未 await,它可能导致潜在的异常或错误的结果。

    下列代码中的CopyToAsync如果持续时间很长,将抛出 ObjectDisposedException:

    1. //修改前
    2. using (var stream = new FileStream("newfile.txt", FileMode.Open))
    3. {
    4.     newStream.CopyToAsync(stream);
    5. }
    6. //修改后
    7. using (var stream = new FileStream("newfile.txt", FileMode.Open))
    8. {
    9.     await newStream.CopyToAsync(stream);
    10. }

    5.从嵌套 Task 转换为外部 Task

    这通常发生在将 async/await 关键字与 Task.Factory.StartNew 混用的情况,没有办法等待并获得子任务的结果。

    下列代码中的意图是进行一秒的延迟,但实际不会有任何延迟:

    1. //修改前
    2. public static async Task Demo()
    3. {
    4.     Console.WriteLine("Hello");
    5.     await Task.Factory.StartNew(() => Task.Delay(1000));
    6.     Console.WriteLine("My IO");
    7. }
    8. //修改后
    9. public static async Task Demo()
    10. {
    11.     Console.WriteLine("Hello");
    12.     await Task.Run(() => Task.Delay(1000));
    13.     Console.WriteLine("My IO");
    14. }

    分析器

    但是要完全靠人去识别这些错误有点难度,这里介绍一个查找和纠正 async/await 的常见误用的工具 —— AsyncFixer。

    引用 Nuget 包 AsyncFixer 后, 在 VS 中就会将这些误用视为警告,你也可以像上次的文章一样将严重性调为“错误":

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

    结论

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

  • 相关阅读:
    ZooKeeper监控
    瑞吉外卖(部署维护篇)
    5款令人骄傲的国产优质软件,能让你的电脑办公更加高效
    【每日一题】2760. 最长奇偶子数组-2023.11.16
    Leetcode刷题day2|数组二|977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
    园子周边第3季-博客园T恤:设计初稿第2版预览
    LVS-RD和keepalived集群服务
    卷积神经网络
    基于微信小程序的校运会管理系统设计与实现-计算机毕业设计源码+LW文档
    通信原理学习笔记6-1:数字解调——基础解调链路、匹配滤波器和AWGN信道最佳接收机
  • 原文地址:https://blog.csdn.net/biyusr/article/details/125885818