这两个函数使用async/await/TPL有什么区别?

3

我想我今天已经成功地把自己搞糊涂了。

public void DoSomething1()
{
    Task.Delay(1000);
}

public async void DoSomething2()
{
    await Task.Delay(1000);
}

当调用这两个函数时,它们内部发生的事情有什么区别?使用不返回Taskasync方法的目的是什么?


2
这两个方法同样成功地什么都不做。除了这两个方法在完成无事可做时会消耗少量 CPU 循环以外,它们与 public void DoSomething3(){} 完全相同。 - Servy
在两者中,Task.Delay根本不运行吗? - KDecker
1
它运行了,但没有完成任何任务。这两种方法都是在说:“从现在起一秒钟不做任何事”,这与只是说“什么也不做”是相同的。 - Servy
如果我调用这两个函数中的任何一个,是否在调用它们之间会有任何区别? - KDecker
我的第一条评论为什么没有回答那个问题? - Servy
1个回答

6
这两个函数在被调用时内部发生的事情有什么区别?
DoSomething1是同步方法。因此:
- 它启动异步延迟,然后忽略它。 - 任何来自异步延迟的异常都将被静默忽略。 - 任何来自DoSomething的异常都将直接传递给调用者。
DoSomething2是异步void方法。因此:
- 它启动异步延迟,然后观察它。 - 任何来自异步延迟的异常都会在DoSomething2开始执行时的SynchronizationContext上重新引发。这通常导致程序终止。 - 来自DoSomething2的任何异常也会在该SynchronizationContext上引发,并产生相同的结果。
使用不返回Task的async方法的目的是什么?
async void并不是一件自然的事情。例如,在F#中根本不存在等价物。async void添加到C#/VB中,以使事件处理程序成为异步而无需更改整个事件处理或委托系统。
简而言之,您应避免使用async void,并仅将其用于事件处理程序(或MVVM中的逻辑等效项,例如ICommand.Execute)。

谢谢,我觉得这解决了我的疑惑。而且还让我好好睡了一晚上。 - KDecker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接