1. ホーム
  2. c#

[解決済み] async/await - タスクとvoidをいつ返すか?

2022-03-16 06:12:56

質問

どのような場合に使用するのでしょうか?

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));
}

解決方法は?

  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 の例外は常に "observed"です。トップレベルの非同期メソッドから出た例外は、単に他の扱われない例外と同じように扱われます。 g の例外は決して観測されない。ガベージコレクタがタスクを片付けに来たとき、タスクが例外を発生させたこと、そして誰もその例外を処理しなかったことを見ます。そのとき TaskScheduler.UnobservedTaskException ハンドラが実行されます。このようなことは決してあってはならないことです。あなたの例を使うなら

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

はい、使用します。 asyncawait ここで、例外が発生してもメソッドが正しく動作することを確認します。

詳しくはこちらをご覧ください。 https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming