1. ホーム
  2. c#

C#でasync/awaitを理解する

2023-07-29 20:40:46

質問

C# 5.0のasync / awaitについて学び始めているのですが、全く理解できません。私はそれが並列化のために使用することができる方法を理解していません。以下の非常に基本的なプログラムを試してみました。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Task task1 = Task1();
            Task task2 = Task2();

            Task.WaitAll(task1, task2);

            Debug.WriteLine("Finished main method");
        }

        public static async Task Task1()
        {
            await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
            Debug.WriteLine("Finished Task1");
        }

        public static async Task Task2()
        {
            await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
            Debug.WriteLine("Finished Task2");
        }

    }
}

このプログラムは、単に Task.WaitAll() を呼び出すところでブロックしてしまい、決して終了しません。何か単純なことを見逃しているか、これに関する正しいメンタル モデルを持っていないだけだと思いますが、世の中に出ているブログやMSDN の記事はどれも役に立ちません。

どのように解決するのですか?

まず最初に、私の のイントロから始めることをお勧めします。 async / await でフォローアップし TAP に関する MSDN の公式ドキュメント .

紹介したブログ記事で触れているように、いくつかの Task のメンバーは、TPL の名残であり、純粋な async のコードで使用されません。 new TaskTask.Start は、次のように置き換えます。 Task.Run (または TaskFactory.StartNew ). 同様に Thread.Sleep は、次のように置き換える必要があります。 Task.Delay .

最後に、私が推奨するのは Task.WaitAll を使わないことをお勧めします。 Wait を実行します。 Task を使っている Task.WhenAll . これらの変更により、あなたのコードは次のようになります。

class Program
{
    static void Main(string[] args)
    {
        MainAsync().Wait();
    }

    public static async Task MainAsync()
    {
        Task task1 = Task1();
        Task task2 = Task2();

        await Task.WhenAll(task1, task2);

        Debug.WriteLine("Finished main method");
    }

    public static async Task Task1()
    {
        await Task.Delay(5000);
        Debug.WriteLine("Finished Task1");
    }

    public static async Task Task2()
    {
        await Task.Delay(10000);
        Debug.WriteLine("Finished Task2");
    }
}