【发布时间】:2017-09-22 22:11:56
【问题描述】:
我想在 WinForms 应用程序中的 WinForm 的 FormClosing 事件期间进行一些清理。清理代码是异步的。
FormClosing 处理程序是:
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
await DoCleanupAsync();
// we never get here as the Form is disposed almost as soon as the async cleanup-method executes;
}
,与:
private async Task DoCleanupAsync()
{
Console.WriteLine("stopping..."); // This is output
await Task.Delay(2000);
Console.WriteLine("stopped"); // This is not
}
正在发生的事情是在等待清理代码完成之前处理表单。
顺便说一句,这会导致我在清理期间尝试更新表单(为简单起见,假设表单包含日志输出)的竞争条件,并且我收到 ObjectDisposedException,因为表单已被释放。
如果我在调用 Dispose() 时查看调用堆栈,我可以看到它被触发
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) 未知
,所以我们可以看到 dispose 是直接从 FormClosing 事件触发的,而我自己没有做任何事情。
我可以通过做一些 hacky 来解决这个问题:
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
await DoCleanupAsync();
this.FormClosing -= Form1_FormClosing;
Close();
}
,但我想了解实际情况!
【问题讨论】:
-
您是否尝试过在
e上设置标志以防止在调用DoCleanupAsync()之前关闭? -
当然。一旦您到达await,函数就会返回并从调用
Form1_FormClosing的位置继续执行。您似乎认为执行会暂停直到DoCleanupAsync();完成,但这不是await的意思。 -
您应该阅读更多关于
async/await的工作原理的信息。然后你会自己找到答案。 -
问题是事件不能/不会被等待。因此,即使
DoCleanupAsync仍在运行,就运行时而言,事件已经完成。这样表单的生命周期就结束了。
标签: c# winforms async-await dispose