在什么情况下人们想要使用
public async Task AsyncMethod(int num)
代替
public async void AsyncMethod(int num)
我能想到的唯一情况是,您是否需要能够跟踪其进度的任务 .
此外,在以下方法中,async和await关键字是否不必要?
public static async void AsyncMethod2(int num)
{
await Task.Factory.StartNew(() => Thread.Sleep(num));
}
6 回答
我发现了这篇非常有用的关于
async
和void
的文章,由JérômeLaban撰写:http://www.jaylee.org/post/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void.aspx底线是
async+void
可以使系统崩溃,通常只应在UI端事件处理程序上使用 .我从这些陈述中得到了明确的想法 .
Async Void方法的例外情况无法通过Catch捕获
对于GUI / ASP.NET应用程序,可以使用AppDomain.UnhandledException或类似的catch-all事件来观察这些异常,但是使用这些事件进行常规异常处理是不可维护性的一个因素(它会导致应用程序崩溃) .
异步void方法具有不同的组合语义 . 返回任务或任务的异步方法可以使用await,Task.WhenAny,Task.WhenAll等轻松编写 . 返回void的异步方法不提供通知调用代码已完成的简单方法 . 启动几个异步void方法很容易,但要确定它们何时完成并不容易 . Async void方法将在启动和结束时通知其SynchronizationContext,但自定义SynchronizationContext是常规应用程序代码的复杂解决方案 .
Async Void方法在使用同步事件处理程序时很有用,因为它们直接在SynchronizationContext上引发异常,这类似于同步事件处理程序的行为方式
有关详细信息,请查看此链接https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
我认为你也可以使用
async void
开始后台操作,只要你小心捕捉异常 . 思考?1)通常,你想要返回一个
Task
. 主要的例外应该是当你需要void
返回类型(对于事件) . 如果没有理由不允许让你的呼叫工作,那么为什么不允许呢?2)
async
返回void
的方法在另一个方面是特殊的:它们代表顶级异步操作,并且在您的任务返回异常时有其他规则可以发挥作用 . 最简单的方法是显示差异是一个例子:f
的异常总是"observed" . 离开顶级异步方法的异常被简单地视为任何其他未处理的异常 . 从未观察到g
的异常 . 当垃圾收集器来清理任务时,它会发现该任务导致异常,并且没有人处理该异常 . 发生这种情况时,TaskScheduler.UnobservedTaskException
处理程序会运行 . 你永远不应该让这种情况发生 . 要使用你的例子,是的,在这里使用
async
和await
,如果抛出异常,它们会确保您的方法仍能正常工作 .有关更多信息,请参阅:http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
我的答案很简单,你可以等待void方法错误CS4008无法等待'void'TestAsync e:\ test \ TestAsync \ TestAsync \ Program.cs
因此,如果方法是异步的,那么最好等待,因为你可以放松异步优势 .
调用异步void的问题是你甚至没有得到任务,你无法知道函数的任务何时完成(参见https://blogs.msdn.microsoft.com/oldnewthing/20170720-00/?p=96655)
以下是调用异步函数的三种方法: