1. ホーム
  2. c#

[解決済み] なぜ、複数のawaitではなく、単一のawait Task.WhenAllを選択する必要があるのでしょうか?

2022-03-01 06:03:33

質問

タスクの完了順序にこだわらず、すべて完了させればよい場合、やはり await Task.WhenAll の代わりに、複数の await 例えば DoWork2 よりも優先される方法です。 DoWork1 (とか(その理由は?)

using System;
using System.Threading.Tasks;

namespace ConsoleApp
{
    class Program
    {
        static async Task<string> DoTaskAsync(string name, int timeout)
        {
            var start = DateTime.Now;
            Console.WriteLine("Enter {0}, {1}", name, timeout);
            await Task.Delay(timeout);
            Console.WriteLine("Exit {0}, {1}", name, (DateTime.Now - start).TotalMilliseconds);
            return name;
        }

        static async Task DoWork1()
        {
            var t1 = DoTaskAsync("t1.1", 3000);
            var t2 = DoTaskAsync("t1.2", 2000);
            var t3 = DoTaskAsync("t1.3", 1000);

            await t1; await t2; await t3;

            Console.WriteLine("DoWork1 results: {0}", String.Join(", ", t1.Result, t2.Result, t3.Result));
        }

        static async Task DoWork2()
        {
            var t1 = DoTaskAsync("t2.1", 3000);
            var t2 = DoTaskAsync("t2.2", 2000);
            var t3 = DoTaskAsync("t2.3", 1000);

            await Task.WhenAll(t1, t2, t3);

            Console.WriteLine("DoWork2 results: {0}", String.Join(", ", t1.Result, t2.Result, t3.Result));
        }


        static void Main(string[] args)
        {
            Task.WhenAll(DoWork1(), DoWork2()).Wait();
        }
    }
}

解決方法は?

はい、使用します。 WhenAll なぜなら、すべてのエラーを一度に伝搬させることができるからです。複数の待ち行列を使用すると、先に発生した待ち行列のうちひとつがスローした場合にエラーが発生します。

もう一つの重要な違いは WhenAll は、すべてのタスクが完了するまで待ちます 失敗があっても (障害やキャンセルされたタスク)。手動で順番に待機させると、プログラムの待機したい部分が実際には早期に続行されるため、予期せぬ同時並行性が発生します。

また、欲しいセマンティクスが直接コードに記述されているので、コードを読むのが楽になると思います。