どのようなシナリオで使用したいのか
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
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://learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming