WinFormsアプリケーションでWinFormのFormClosingイベント中にいくつかのクリーンアップを行いたいと思います。クリーンアップコードは非同期です。WinFormsは、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
}
フォームはクリーンアップコードでawaitを前に処分されている完了です。
ちなみに、これは、クリーンアップ中にフォームを更新しようとしている競合状態を引き起こしています(単純にフォームにログ出力が含まれているとします)、フォームが破棄されたため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();
}
を、私は実際に何が起こっているのかを理解したいと思います!
'DoCleanupAsync()'を呼び出す前に 'e'にフラグを立てて、閉じられないようにしましたか? – DiskJunky
もちろん。 _await_に到達するとすぐに、関数が戻り、 'Form1_FormClosing'が呼び出された場所から実行が続けられます。 'DoCleanupAsync();'が終了するまで実行が停止すると思っているようですが、 'await'が意味するものではありません。 – oerkelens
'async/await'の仕組みの詳細を読むべきです。それであなたは自分で答えを見つけるでしょう。 – dymanoid