LoginSignup
3
3

More than 1 year has passed since last update.

async/await 非同期メソッドの待ちかた調査

Posted at

async/await 非同期メソッドの待ちかた

async/awaitを使うと数珠繋ぎでasync/awaitが連鎖しがち。
そんな時に非同期処理を同期として呼び出したい場合に以下の2パターンが多い様子。。

  • task.GetAwaiter().GetResult()
  • task.Wait()

例外で差分があるようなので比較した。

Wait()

ソース

namespace Sandbox
{
    using System;
    using System.Threading.Tasks;

    class Program
    {
        static async Task Main(string[] args)
        {
            try
            {
                Console.WriteLine($"{DateTime.Now} start");
                Task.Run(HeavyFunctionAsync).Wait();
                Console.WriteLine($"{DateTime.Now} end");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public static async Task HeavyFunctionAsync()
        {
            for (var i = 0; i < 5; i++)
            {
                await Task.Delay(1000);
                Console.WriteLine($"{DateTime.Now} N={i}");
            }

            throw new InvalidOperationException("exception");

            return;
        }
    }
}

結果

AggregrateExceptinoとして捕捉。InnerException見る必要があるのがメンドクサイ。

2021/06/05 21:30:30 start
2021/06/05 21:30:32 N=0
2021/06/05 21:30:33 N=1
2021/06/05 21:30:34 N=2
2021/06/05 21:30:35 N=3
2021/06/05 21:30:36 N=4
System.AggregateException: One or more errors occurred. (exception)
 ---> System.InvalidOperationException: exception
   at Sandbox.Program.HeavyFunctionAsync() in D:\work\Repos\Sandbox\Sandbox\Program.cs:line 30
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at Sandbox.Program.Main(String[] args) in D:\work\Repos\Sandbox\Sandbox\Program.cs:line 13

GetAwaiter().GetResult()

ソース。

namespace Sandbox
{
    using System;
    using System.Threading.Tasks;

    class Program
    {
        static async Task Main(string[] args)
        {
            try
            {
                Console.WriteLine($"{DateTime.Now} start");
                Task.Run(HeavyFunctionAsync).GetAwaiter().GetResult();
                Console.WriteLine($"{DateTime.Now} end");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public static async Task HeavyFunctionAsync()
        {
            for (var i = 0; i < 5; i++)
            {
                await Task.Delay(1000);
                Console.WriteLine($"{DateTime.Now} N={i}");
            }

            throw new InvalidOperationException("exception");

            return;
        }
    }
}

結果

InvalidOperationExceptionとして捕捉。

2021/06/05 21:27:48 start
2021/06/05 21:27:49 N=0
2021/06/05 21:27:50 N=1
2021/06/05 21:27:51 N=2
2021/06/05 21:27:52 N=3
2021/06/05 21:27:53 N=4
System.InvalidOperationException: exception
   at Sandbox.Program.HeavyFunctionAsync() in D:\work\Repos\Sandbox\Sandbox\Program.cs:line 30
   at Sandbox.Program.Main(String[] args) in D:\work\Repos\Sandbox\Sandbox\Program.cs:line 13

結論

Wait()は良くある別タスク内で発生した例外同様AggreateExceptinoでまとめてChatchされる。
一方でGetAwaiter().GetResult()は同期メソッドで例外が発生したかの如く、発生時の状態で補足される。

個人的にはGetAwaiter().GetResult()の方が好きだが別意見の人もいそう

3
3
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3