615

どのようなシナリオで使用したいですか

public async Task AsyncMethod(int num)

それ以外の

public async void AsyncMethod(int num)

私が考えることができる唯一のシナリオは、タスクの進行状況を追跡できるようにする必要がある場合です。

また、次の方法では、async および await キーワードは不要ですか?

public static async void AsyncMethod2(int num)
{
    await Task.Factory.StartNew(() => Thread.Sleep(num));
}
4

6 に答える 6

499
  1. 通常、 を返したいと思うでしょうTask。主な例外は、(イベントの) 戻り値の型が必要な場合です。void発信者がawaitあなたの仕事をすることを禁止する理由がないのなら、なぜそれを許可しないのですか?

  2. async返されるメソッドvoidは、別の側面で特別です。トップレベルの非同期操作を表し、タスクが例外を返したときに適用される追加のルールがあります。違いを示す最も簡単な方法は、例を使用することです。

static async void f()
{
    await h();
}

static async Task g()
{
    await h();
}

static async Task h()
{
    throw new NotImplementedException();
}

private void button1_Click(object sender, EventArgs e)
{
    f();
}

private void button2_Click(object sender, EventArgs e)
{
    g();
}

private void button3_Click(object sender, EventArgs e)
{
    GC.Collect();
}

fの例外は常に「監視」されます。最上位の非同期メソッドを終了する例外は、他の未処理の例外と同様に単純に処理されます。gの例外は観察されません。ガベージ コレクターがタスクをクリーンアップするようになると、タスクの結果が例外であり、誰もその例外を処理していないことがわかります。その場合、TaskScheduler.UnobservedTaskExceptionハンドラーが実行されます。これを絶対に許してはいけません。あなたの例を使用するには、

public static async void AsyncMethod2(int num)
{
    await Task.Factory.StartNew(() => Thread.Sleep(num));
}

はい、使用asyncし、awaitここで、例外がスローされた場合でもメソッドが正しく機能することを確認します。

詳細については、https ://docs.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming を参照してください。

于 2012-08-27T14:53:45.313 に答える
55

asyncジェローム・voidラバン について書かれたこの非常に役立つ記事に出くわしました: https://jaylee.org/archive/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void .html

結論として、 はシステムをクラッシュさせるasync+void可能性があるため、通常は UI 側のイベント ハンドラーでのみ使用する必要があります。

この背後にある理由は、AsyncVoidMethodBuilder によって使用される同期コンテキストであり、この例ではありません。アンビエント同期コンテキストがない場合、async void メソッドの本体によって処理されない例外は、ThreadPool で再スローされます。この種の未処理の例外がスローされる可能性のある論理的な場所は他にないように見えますが、.NET 2.0 以降、ThreadPool の未処理の例外がプロセスを効果的に終了させるため、残念なことにプロセスが終了します。AppDomain.UnhandledException イベントを使用してすべての未処理の例外をインターセプトできますが、このイベントからプロセスを回復する方法はありません。

UI イベント ハンドラーを記述する場合、async void メソッドは、非 async メソッドと同じように例外が処理されるため、なんらかの苦痛を伴いません。Dispatcher でスローされます。このような例外から回復する可能性はありますが、ほとんどの場合はそれで十分です。ただし、UI イベント ハンドラー以外では、async void メソッドを使用するのは危険であり、見つけるのは簡単ではありません。

于 2014-04-11T15:40:55.977 に答える
-1

私の答えは簡単です。voidメソッドを待つことはできません

Error   CS4008  Cannot await 'void' TestAsync   e:\test\TestAsync\TestAsyncProgram.cs

したがって、メソッドが の場合、asyncの利点を失う可能性があるため、待機可能にする方がよいでしょうasync

于 2018-09-20T16:21:00.737 に答える