如何在C#中调用异步void事件处理程序?

Eyv*_*ind 6 .net c# event-handling async-await

如果我将我的事件处理程序声明为async void,它们是由.NET框架同步还是异步调用的?

即,给出以下代码:

async void myButton_click(object sender, EventArgs e) {
   do stuff
   await longRunning()
   do more stuff
}
Run Code Online (Sandbox Code Playgroud)

我可以确定在GUI线程上执行"do stuff"行吗?

Sri*_*vel 10

事件处理程序将被同步调用,并且不等待(等待)直到事件处理程序完成,但等待直到事件处理程序返回.

如果以前的句子足够混乱,我会尽力解释清楚.当执行所有等待点并且已到达方法体的末尾或执行任何return语句时,异步方法完成(忽略异常).但是,只要您找到Task尚未完成的第一个await语句,异步方法就会返回.换句话说,异步方法可以返回几次,但只能完成一次.

所以现在我们知道异步方法何时完成并返回.事件处理程序将假定您的方法一旦返回就完成,而不是在实际完成时.

一旦事件处理程序到达第一个await语句,它将返回,如果有更多方法附加到同一个事件处理程序,它将继续执行它们而不等待异步方法完成.

是的,do stuff如果UI线程触发事件,do more stuff将在UI线程中执行,并且只要longRunning().ConfigureAwait(false)未调用,也将在UI线程中执行yes .

  • 谢谢,你的第一句话对我来说足够了:) (2认同)
  • @SriramSakthivel:是的.我这样想:每种方法都是独立的; 它在`await`捕获它自己的上下文并在该上下文中恢复.因此,如果调用堆栈中的某个方法没有在其上下文中恢复,则无关紧要. (2认同)

i3a*_*non 6

它们将像调用任何其他非async-await方法一样被调用:

Click(this, EventArgs.Empty);
Run Code Online (Sandbox Code Playgroud)

因为这个特定的事件处理程序是一个async方法,所以调用将同步运行,直到await到达 an 为止,其余的将继续。这意味着它do stuff是在 GUI 线程上同步执行的。然后调用者继续前进,而不知道操作async尚未完成。

do more stuff也将在 GUI 线程上执行,但原因不同。在SynchronizationContextGUI 环境中,确保将延续发布到单个 GUI 线程,除非您明确告诉它不要这样做await longRunning().ConfigureAwait(false)