为什么异步方法中的异常在 C# 中是“危险的”
在使用 C# 或任何其他语言开发企业系统时,错误处理是一个有时会被忽略的主题,因为市场上有许多工具可以让我们轻松安装和配置,并且所有异常都开始自动登录。但是,如果记录了错误的异常怎么办?如果我们的应用程序隐藏了重要错误并掩盖了问题的真正原因,该怎么办?对于很多开发者来说,这可能是一个荒谬的假设,但在现实世界的场景中,这种情况比我们有时想象的更为普遍。
要d Ë monstrate什么,我想用这短短的文章说,看看下面的代码:
如果我们运行这个控制台应用程序,你认为会发生什么?考虑到MyAsyncMethod故意抛出 ArgumentException,对许多人来说最合乎逻辑的结果是代码的执行将跳转到catch块(第 9 行)。但是,一旦我们运行代码,这就是实际发生的事情:


没有抛出异常,因为没有等待 MyAsyncMethod 例程,并且异常会随着任务而丢失。在这种情况下,如果我们使用 Application Insights 或其他日志系统,则永远不会记录异常,我们将无法知道发生了异常。我什至不是在谈论我们应该怎么做才能在应用程序中正确处理这个错误。因此,如果我们想在父方法中捕获错误,第一个错误不是等待任务。如果我们使用“await”关键字,则会抛出异常:




这解决了单个简单任务的问题,但是如果我们在一个方法中运行多个任务怎么办?结果如何?如果我们不等待任何任务,结果将类似于前一个带有单个任务的示例:异常将随任务一起丢失。但是,如果我们等待所有任务,考虑到可能抛出多个异常,每个任务一个,父方法的结果可能不是我们期望的。
下面的代码代表了对上一个示例的修改,包括一个运行两个任务并等待它们执行的方法:
如果我们再次运行控制台应用程序,结果如下:


它实际上显示了两个异常的消息,但我们没有获得有关子方法抛出的每个异常的更多详细信息的可能性。如果我们调试结果,它表明我们有两个异常,但不可能在日志记录方面做更准确的事情:


如上图突出显示,异常表明它实际上代表了两个异常,但 Exception 类的正常属性只允许我们看到其中一个(异常任务 1)。如何解决?
在 child 方法中,我们可以捕获更具体的异常 ( AggregateException ) 并循环遍历多个异常,正确处理它们并应用我们想要的错误策略:


通过这种修改,我们能够捕获所有异常,专门处理AggregateException,它包含一个属性 InnerExceptions,允许我们遍历每个异常。结果是这样的:


如您所见,子方法显示了两个异常,并且根本没有命中父方法上的 catch 块。选择采用哪种方法取决于您正在处理的上下文,但我们必须始终牢记两件事:
1- 在未等待的任务中丢失异常是不好的
2- 在某些情况下,处理和捕获所有异常非常重要,并尽可能详细
感谢您阅读这篇快速文章直到最后。如果您有任何问题或意见,请在此留下。我很乐意谈论它。

浙公网安备 33010602011771号