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



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

即,给定以下代码:

async void myButton_click(object sender, EventArgs e) {
   do stuff
   await longRunning()
   do more stuff
}

我可以确定"做事"行将在 GUI 线程上执行吗?

事件处理程序将被同步调用,并且不会等待(await(直到事件处理程序完成,而是等到事件处理程序返回。

如果前面的句子足够混乱,我会试着解释清楚。当执行所有等待点并且到达方法主体的末尾或执行任何返回语句时,异步方法完成(忽略异常(。但是异步方法会在您点击尚未完成的Task的第一个 await 语句后立即返回。换句话说,异步方法可以返回多次,但只能完成一次。

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

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

是的,如果 UI 线程触发事件,do stuff将在 UI 线程中执行,

是的,只要不调用longRunning().ConfigureAwait(false)do more stuff也会在 UI 线程中执行。

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

Click(this, EventArgs.Empty);

由于此特定事件处理程序是async方法,因此调用将同步运行,直到达到await,其余部分将是延续。这意味着do stuff在 GUI 线程上同步执行。然后,调用方在不知道async操作尚未完成的情况下继续前进。

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

相关内容

  • 没有找到相关文章