こんにちは。弱小エンジニアのいすいです。
最近の仕事では、引き継いだPJのコードリファクタリングを主に行っています!
その中でTaskの使い方が気になったので、まとめました。
Taskを使うべき場所
引き継いだコードでは至る所にTaskが散りばめられていました。
とりあえずTaskにしとこ!って前任者は考えていたのでしょう。。
当たり前ですが、非同期処理が必要ないところでTaskを使って非同期処理をしても意味がないので、非同期処理が必要な箇所に絞りました。
よくある非同期処理はファイル読み込みや、APIアクセス、DBアクセスなどのイメージですしたので、その辺りをリファクタしました。
awaitで待機するタイミング
戻り値がTask型だと、awaitで待機すると思いますが、
すぐにawaitで待たない方が良いなという時がありました。
それは複数の非同期処理をまとめて待機したい時です。
以下はコードの例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Task taskA = Task.Run(()=> { Thread.Sleep(3000); }); Task taskB = Task.Run(()=> { Thread.Sleep(3000); }); Task taskC = Task.Run(()=> { Thread.Sleep(3000); }); // ここでまとめてawait await Task.WhenAll(taskA, taskB, taskC); |
こうすることで、taskA,taskB,TaskCを非同期で処理できます。
awaitの階層
awaitの中でawaitした時どうなるのか混乱したのでまとめました。
awaitしている処理の中でさらにawaitをすると、メインスレッドに呼び出し元が戻ります。
例えば以下の場合、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
void MethodA() { MethodB(); Console.WriteLine("A"); } async void MethodB() { await MethodC(); Console.WriteLine("B"); } async Task MethodC() { await Task.Run(()=> { Thread.Sleep(3000); Console.WriteLine("C"); }); } |
実行すると、
1 2 3 |
A C B |
の順番で出力されます。
MethodCで3秒スリープしている間に、MethodAがメインスレッドで処理を進め、MethodCが完了したあと、MethodBが最後まで実行されます。
ちなみに、MethodCの処理中にMethodAの処理は完了してしまうことになります。
処理Aの中でawaitするとその先の処理A自体は止まってしまうので、
awaitの先も待たずに処理したい場合には処理Aの中でawaitを読んではいけないので、全てawaitで呼び出すというわけでもないのです。
async voidはだめ?
ネットにはasync voidは使わないほうが良いという記事があったりするのですが、
個人的にはasync voidを使って良いと思っています🧐🧐🧐
損はないからasync Taskにしとけってことですかね。。
でもTaskをawaitで呼ばない時、VisualStudioでawaitがないよって言われちゃうんですけどね。(エラーにはならないけど)
他にはTask.Wait()はデッドロックのリスクがあるので、しない方がいいみたいですね。
あまり良く理解していませんが、これはとりあえずしないように気をつけとこうと思います。
Taskを入れ子にしても意味ない
引き継いだコードには、Taskが入れ子のようになっているものがありました。
例えば以下のようなものです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
async void MethodA() { await Task.Run(async ()=> { await MethodB(); }); } async Task MethodB() { await Task.Run(()=> { Thread.Sleep(3000); }); } |
awaitしている間は受け待ちになるので、以下のコードと同じです。
1 2 3 4 5 6 7 |
async void MethodA() { await Task.Run(()=> { Thread.Sleep(3000); } } |
状況によりけりなのでどれが良いとか断言できないですが、できるだけ無駄なことは避けたいところです。
Taskを正確に使えるようにまだまだ頑張ります。

How is the COVID situation over there?
Leave me alone, I’m just taking a look
Have an upvote. And a comment mostly so I can find this thread easily and study from time to time. Refreshers never hurt. Thank you!
Happy everyday!