我想在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()时查看callstack,我可以看到它是从
触发的System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m)Unknown
,所以我们可以看到dispose是直接从FormClosing事件触发的,而我自己也没有。
我可以做一些像hacky这样的事情来解决这个问题:
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
await DoCleanupAsync();
this.FormClosing -= Form1_FormClosing;
Close();
}
,但我想了解实际发生了什么!
答案 0 :(得分:1)
实际上是什么
当您await
async
方法时,控制流会返回到Form1_FormClosing
方法的调用方。当您此时未设置e.Cancel
标志时,表单将被关闭。
当Task
返回的DoCleanupAsync
完成后,将恢复执行处理程序。但是表格已经关闭了。