web-dev-qa-db-ja.com

コンソールアプリケーションでasync / awaitを使用するときにAsyncContextが必要なのはなぜですか?

コンソールアプリケーション内で非同期メソッドを呼び出しています。アプリが起動した直後、つまり待機可能なタスクが完了する前にアプリを終了したくありません。私はこれを行うことができるようです:

_internal static void Main(string[] args)
{
    try
    {
        Task.WaitAll(DoThisAsync());
    }
    catch (Exception ex)
    {
        Console.Error.WriteLine(ex);
        throw;
    }
}

internal static async Task DoThisAsync()
{
    //...
}
_

しかし Stephen Clearyの記事 によると、私はそれを行うことができないようで、代わりに非同期が完了したときに戻るための何らかのコンテキストを作成する必要があります(例 AsyncContext ) 。

上記のコードは機能しますが、メインスレッドでTask.WaitAll(DoThisAsync());の後に返されるので、カスタムコンテキストを使用する必要があるのはなぜですか。

12
rory.ap

必須ではありません。それは私の好みです。

Main内のタスクを同期的にブロックできます(Wait/Result/WaitAllを使用)。セマンティクスは少し異なります。特に、非同期コードが失敗した場合、Wait/Result/WaitAllは例外をAggregateExceptionにラップし、AsyncContextではない。

また、AsyncContextはメインスレッドを特別に扱います。継続をスレッドプールに送信する代わりに、継続をそのメインスレッドに送信します(デフォルトでは、これを回避するために常にConfigureAwait(false)を使用できます)。 AsyncContextはUIコンテキストと非常に似た動作をするため、「概念実証」コンソールアプリを作成している場合は、これが便利です。

しかし結局のところ、それは好みの問題です。

24
Stephen Cleary