如果我将事件处理程序声明为async void
,它们是否会被.NET框架同步或异步调用?
即,给出以下代码:
async void myButton_click(object sender, EventArgs e) {
do stuff
await longRunning()
do more stuff
}
我可以确定在GUI线程上执行“do stuff”行吗?
答案 0 :(得分:9)
事件处理程序将被同步调用,并且不等待(等待)直到事件处理程序完成,但等待直到事件处理程序返回。
如果上一句话容易混淆,我会尽力解释清楚。当执行所有等待点并且已到达方法体的末尾或执行任何return语句时,异步方法完成(忽略异常)。但是,只要您点击尚未完成的Task
的第一个await语句,异步方法就会返回。换句话说,异步方法可以返回几次,但只能完成一次。
现在我们知道异步方法何时完成并返回。事件处理程序将假定您的方法一返回就完成了,而不是实际完成时。
一旦你的事件处理程序到达第一个await
语句,它就会返回,如果有更多的方法附加到同一个事件处理程序,它将继续执行它们而不用等待异步方法来完成。
是的,如果UI线程触发事件,do stuff
将在UI线程中执行,只要do more stuff
未被调用,也将在UI线程中执行是longRunning().ConfigureAwait(false)
。
答案 1 :(得分:4)
将调用它们,就像调用任何其他非async-await
方法一样:
Click(this, EventArgs.Empty);
因为此特定事件处理程序是async
方法,所以调用将同步运行,直到达到await
,其余的将是延续。 这意味着do stuff
在GUI线程上同步执行。然后调用者继续前进,而不知道async
操作尚未完成。
do more stuff
也将在GUI线程上执行,但原因不同。 GUI环境中的SynchronizationContext
确保将延续发布到单个GUI线程,除非您明确告诉它不要使用await longRunning().ConfigureAwait(false)