web-dev-qa-db-ja.com

「非同期void」イベントハンドラーを避ける必要がありますか?

一般に、火をつけて忘れるasync voidタスクを開始するためのメソッド。保留中のタスクの追跡がなく、そのようなメソッド内でスローされる可能性のある例外を処理するのが難しいためです。

通常、async voidイベントハンドラも同様ですか?たとえば、

private async void Form_Load(object sender, System.EventArgs e)
{
        await Task.Delay(2000); // do async work
        // ...
} 

このように書き換えることができます:

Task onFormLoadTask = null; // track the task, can implement cancellation

private void Form_Load(object sender, System.EventArgs e)
{
        this.onFormLoadTask = OnFormLoadTaskAsync(sender, e);
} 

private async Task OnFormLoadTaskAsync(object sender, System.EventArgs e)
{
        await Task.Delay(2000); // do async work
        // ...
} 

再入可能性に加えて、非同期イベントハンドラーの水中岩は何ですか?

103
avo

ガイドラインは、async voidexceptイベントハンドラで使用する場合は、async voidイベントハンドラでOKです。

とはいえ、ユニットテストの理由で、すべてのasync voidメソッド。例えば。、

public async Task OnFormLoadAsync(object sender, EventArgs e)
{
  await Task.Delay(2000);
  ...
}

private async void Form_Load(object sender, EventArgs e)
{
  await OnFormLoadAsync(sender, e);
}
137
Stephen Cleary

一般に、非同期voidイベントハンドラーも避けるべきですか?

一般的に、イベントハンドラーは、無効な非同期メソッドが潜在的なコード臭ではない1つのケースです。

さて、何らかの理由でタスクを追跡する必要がある場合、説明する手法は完全に合理的です。

42
Eric Lippert

はい、通常、イベントハンドラーの非同期ボイドが唯一のケースです。詳細については、チャンネル9のすばらしいビデオをご覧ください。

The only case where this kind of fire-and-forget is appropriate is in top-level event-handlers. Every other async method in your code should return "async Task".

リンク

5
DotNet Dreamer

ReSharperを使用する場合、無料の ReCommended Extension が役立ちます。 「非同期void」メソッドを分析し、不適切に使用された場合に強調表示します。この拡張機能は、非同期voidのさまざまな使用法を区別し、ここで説明する適切なクイックフィックスを提供できます。 ReCommended-Extension wiki

3