Winform 在 FormClosing 事件期间仍在等待任务时被释放
Winform is disposed while still awaiting a task during the FormClosing event
我想在 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 事件触发的,我自己没有做任何事情。
我可以通过做一些骇人听闻的事情来解决这个问题:
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
await DoCleanupAsync();
this.FormClosing -= Form1_FormClosing;
Close();
}
,但我想了解实际情况!
what's actually going on
当您 await
一个 async
方法时,控制流 returns 到 Form1_FormClosing
方法的调用者。而当你此时没有设置e.Cancel
标志时,窗体是关闭的。
当 DoCleanupAsync
返回的 Task
完成时,您的处理程序将恢复执行。但是表格已经关闭了。
我想在 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 事件触发的,我自己没有做任何事情。
我可以通过做一些骇人听闻的事情来解决这个问题:
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
await DoCleanupAsync();
this.FormClosing -= Form1_FormClosing;
Close();
}
,但我想了解实际情况!
what's actually going on
当您 await
一个 async
方法时,控制流 returns 到 Form1_FormClosing
方法的调用者。而当你此时没有设置e.Cancel
标志时,窗体是关闭的。
当 DoCleanupAsync
返回的 Task
完成时,您的处理程序将恢复执行。但是表格已经关闭了。