C#のTaskクラスの注意点

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

最近仕事でコードのリファクタリングを行っていて、

その中でTaskの使い方を再認識したので、今回まとめてみました。

Taskを使うべき場所

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

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

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

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

awaitで待機するタイミング

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

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

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

以下はコードの例です。

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をすると、メインスレッドに呼び出し元が戻ります。

例えば以下の場合、

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");
     });
}

実行すると、

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

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

async void MethodA()
{
    await Task.Run(async ()=>
    {
         await MethodB();
    });
}

async Task MethodB()
{
    await Task.Run(()=>
    {
         Thread.Sleep(3000);
     });
}

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

async void MethodA()
{
    await Task.Run(()=>
    {
         Thread.Sleep(3000);
     }
}

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

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

SNSでもご購読できます。

コメント

  1. How is the COVID situation over there?

  2. 择偶网 より:

    Leave me alone, I’m just taking a look

  3. Anime Porn より:

    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!

  4. Backlinks より:

    Happy everyday!

コメントを残す

*