1. ホーム
  2. c#

[解決済み] .NET 4.5で2つの非同期タスクを並列に実行し、結果を収集する

2022-06-22 11:16:58

質問

私は、簡単だと思われるものを.NET 4.5で動作させるために、しばらく試してきました。

私は、2 つの長く実行されているタスクを同時に起動し、そのタスクから

の結果をC# 4.5 (RTM)の最適な方法で収集したい。

以下は動作しますが、私はこれが好きではありません。

  • 私は Sleep を非同期メソッドにすることです。 await 他のメソッド
  • で不器用に見えるだけです。 Task.Run()
  • これでは、新しい言語機能を全く使っているとは思えませんね

動作中のコードです。

public static void Go()
{
    Console.WriteLine("Starting");

    var task1 = Task.Run(() => Sleep(5000));    
    var task2 = Task.Run(() => Sleep(3000));

    int totalSlept = task1.Result + task2.Result;

    Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}

private static int Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    Thread.Sleep(ms);
    Console.WriteLine("Sleeping for " + ms + " FINISHED");
    return ms;
}

動作しないコードです。

更新:これは実際に動作し、正しい方法です。 Thread.Sleep

このコードが動作しないのは Sleep(5000) を呼び出すとすぐにタスクの実行を開始するので Sleep(1000) はそれが完了するまで実行されません。これは Sleepasync となっており、私は await を呼び出したり .Result が早すぎる。

もしかしたらと思い、実行されていない Task<T> を呼び出すことで async メソッドを呼び出すことで Start() を呼び出すことができるのですが、2つのタスクに対して Task<T> を取得する方法がわかりません。

public static void Go()
{
    Console.WriteLine("Starting");

    var task1 = Sleep(5000);    // blocks
    var task2 = Sleep(1000);

    int totalSlept = task1.Result + task2.Result;

    Console.WriteLine("Slept for " + totalSlept + " ms");
}

private static async Task<int> Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    Thread.Sleep(ms);
    return ms;
}

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

非同期プログラミングでSleepの代わりにTask.Delayを使用し、Task.WhenAllでタスクの結果を結合する必要があります。タスクは並列に実行されることになります。

public class Program
    {
        static void Main(string[] args)
        {
            Go();
        }
        public static void Go()
        {
            GoAsync();
            Console.ReadLine();
        }
        public static async void GoAsync()
        {

            Console.WriteLine("Starting");

            var task1 = Sleep(5000);
            var task2 = Sleep(3000);

            int[] result = await Task.WhenAll(task1, task2);

            Console.WriteLine("Slept for a total of " + result.Sum() + " ms");

        }

        private async static Task<int> Sleep(int ms)
        {
            Console.WriteLine("Sleeping for {0} at {1}", ms, Environment.TickCount);
            await Task.Delay(ms);
            Console.WriteLine("Sleeping for {0} finished at {1}", ms, Environment.TickCount);
            return ms;
        }
    }