C#Taskの備忘録

こんにちは。弱小エンジニアのいすいです。

最近の仕事では、引き継いだPJのコードリファクタリングを主に行っています!

その中でTaskの使い方が気になったので、まとめました。

Taskを使うべき場所

引き継いだコードでは至る所にTaskが散りばめられていました。

とりあえずTaskにしとこ!って前任者は考えていたのでしょう。。

当たり前ですが、非同期処理が必要ないところでTaskを使って非同期処理をしても意味がないので、非同期処理が必要な箇所に絞りました。

よくある非同期処理はファイル読み込みや、APIアクセス、DBアクセスなどのイメージですしたので、その辺りをリファクタしました。

awaitで待機するタイミング

戻り値がTask型だと、awaitで待機すると思いますが、

すぐにawaitで待たない方が良いなという時がありました。

それは複数の非同期処理をまとめて待機したい時です。

以下はコードの例です。

こうすることで、taskA,taskB,TaskCを非同期で処理できます。

awaitの階層

awaitの中でawaitした時どうなるのか混乱したのでまとめました。

awaitしている処理の中でさらにawaitをすると、メインスレッドに呼び出し元が戻ります。

例えば以下の場合、

実行すると、

の順番で出力されます。

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が入れ子のようになっているものがありました。

例えば以下のようなものです。

awaitしている間は受け待ちになるので、以下のコードと同じです。

状況によりけりなのでどれが良いとか断言できないですが、できるだけ無駄なことは避けたいところです。

Taskを正確に使えるようにまだまだ頑張ります。

SNSでもご購読できます。

コメントを残す

*