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 完成时,您的处理程序将恢复执行。但是表格已经关闭了。