I'm wanting to do some cleanup during the FormClosing event of a WinForm in a WinForms application. The cleanup code is async.
The FormClosing hander is:
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;
}
, with:
private async Task DoCleanupAsync()
{
Console.WriteLine("stopping..."); // This is output
await Task.Delay(2000);
Console.WriteLine("stopped"); // This is not
}
What's happening is the Form is being disposed of before the await on the cleanup code is complete.
Incidentally, this is causing a race condition where I'm trying to update the form (for simplicity let's say the form contains log output) during the cleanup and I get an ObjectDisposedException because the form has been disposed.
If I look at the callstack when Dispose() is called, I can see it's being triggered from
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) Unknown
, so we can see that the dispose is being triggered directly from the FormClosing event, and nothing that I'm doing myself.
I can work around this by doing something hacky like:
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
await DoCleanupAsync();
this.FormClosing -= Form1_FormClosing;
Close();
}
, but I'd like to understand what's actually going on!