【问题标题】:What is the difference between "async void" and skipping "await" keyword in C#? [duplicate]C# 中“async void”和跳过“await”关键字有什么区别? [复制]
【发布时间】:2020-05-13 09:39:23
【问题描述】:

有什么区别

MyFireAndForgetMethod();   
public async void MyFireAndForgetMethod(){}

MyFireAndForgetMethod(); // Will have a warning here
public async Task MyFireAndForgetMethod(){}

我不确定在 FireAndForget 调用中使用哪个指标。

【问题讨论】:

  • 您已经发现了一个差异。使用async Task 方法会收到警告,而其他方法则不会。 “有什么区别”问题通常过于宽泛,因为它们会引起广泛的讨论和回答,而没有任何明确的解决方案。而且您的问题没有显示出任何真正的证据表明您已经努力自己调查这些差异。标记的重复确实提供了大量关于您可能感兴趣的一些可能差异的信息,以及关于如何以及为什么处理这些差异的有用建议.
  • 我发现这很有帮助,尽管它可能不是您想要的答案:C# async/await with/without awaiting (fire and forget)
  • 如果您之前阅读过我的答案,我会重新编写。

标签: c# .net-core


【解决方案1】:

区别在于async void 用于触发和忘记调用,通常是事件处理程序,async Task ot async Task<T> 是正常情况。

Task 对象用于await 完成方法、检索结果并使用标准trycatch 捕获可能的异常。

【讨论】:

  • 一劳永逸只会吞下异常并导致比赛条件。它不应该在你的代码中成为真实的东西。
【解决方案2】:

你不应该写async void method,因为你不能等待它。而且您应该始终等待异步,否则您会吞下异常。如果您从函数返回没有任何意义,只需返回 non-generic Task 的实例 - 因此可以等待它。

“Fire and Forget 很好——只要你永远实际上忘记。”对于多种形式的多任务处理,吞咽异常存在整个问题。来自它的TPL suffers as badly 是多线程。 Task 的执行可能会引发异常。而那些可以是fatal ones, wich should never be caught - 更不用说默默地吞下(被遗忘了)。通常你必须编写非常糟糕的 try/catch 代码,但对于多任务,你必须积极避免它。 Task 和 Await,是您如何避免它(而不是实际上忘记)。虽然 async void 是(几乎)保证吞咽

Task 实例带有the Exceptions in a neat list。等待将重新抛出它们。由于 Multtiasking,No Exception 不会被吞下(你当然还有其他方法来搞砸那部分)。

如果您没有合适的地方等待,您可以编写一个子任务,其唯一目的是查看和处理它的父异常。但是,您仍然必须终止 Fatal 或 Boneheaded Excetpions 上的进程,并最终得到重复的异常处理程序。最好在主程序流程中等待所有内容,您希望在该流程中获得全局日志记录代码。

【讨论】:

  • 虽然这里有一些很好的建议,但对于所提出的 question 而言,没有什么比这更遥远的答案了,即 这两种结构之间的区别是什么.
  • @PeterDuniho One 从来没有机会抛出异常。这就是我回答的整个第二半。副本中接受的答案是用更少的文字或细节说我所做的同样的事情。并且永远不会提到除了返回值(我的答案的前半部分)可能会有影响。
  • “从来没有一个地方可以抛出异常[原文如此]”——嗯?任何一个都可以在任何他们想要的地方抛出异常。并且从未观察到的Task 与根本不返回Task 的异步方法在异常方面没有什么不同。在任何一种情况下,都不会观察到引发的异常。所以,不......你的答案中的第二段以任何方式回答了所提出的问题,这甚至都不是真的。
  • @PeterDuniho 做了一些返工。这能正确回答问题吗?
猜你喜欢
  • 1970-01-01
  • 2021-08-25
  • 2018-05-10
  • 2012-03-20
  • 2019-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多