32

理想的には、ノンブロッキング モードでタスクを遅らせてから、すべてのタスクが完了するのを待ちます。Task.Delay によって返されるタスク オブジェクトを追加してから、Task.WaitAll を使用しようとしましたが、これは役に立たないようです。この問題を解決するにはどうすればよいですか?

class Program
{
    public static async void Foo(int num)
    {
        Console.WriteLine("Thread {0} - Start {1}", Thread.CurrentThread.ManagedThreadId, num);

        var newTask = Task.Delay(1000);
        TaskList.Add(newTask);
        await newTask;

        Console.WriteLine("Thread {0} - End {1}", Thread.CurrentThread.ManagedThreadId, num);
    }

    public static List<Task> TaskList = new List<Task>();

    public static void Main(string[] args)
    {
        for (int i = 0; i < 3; i++)
        {
            int idx = i;
            TaskList.Add(Task.Factory.StartNew(() => Foo(idx)));
        }

        Task.WaitAll(TaskList.ToArray());
    }
}
4

2 に答える 2

30

注意すべきことは、Foo は非同期であるため、それ自体が Task であるということです。あなたの例には、単にタスクを開始するFooタスクがありますが、それを待たないでください。

つまり、Task.WaitAll(TaskList.ToArray())はそれぞれのタスクが開始されるのを単に待っているだけTask.Delayで、これらのタスクがすべて終了するのを待っているわけではありません。

これはあなたが達成しようとしているものかもしれません:

class Program
{
    public static async Task Foo(int num)
    {
        Console.WriteLine("Thread {0} - Start {1}", Thread.CurrentThread.ManagedThreadId, num);

        var newTask = Task.Delay(1000);

        await newTask;
        Console.WriteLine("Thread {0} - End {1}", Thread.CurrentThread.ManagedThreadId, num);

    }

    public static List<Task> TaskList = new List<Task>();

    public static void Main(string[] args)
    {
        for (int i = 0; i < 3; i++)
        {
            int idx = i;

            Task fooWrappedInTask = Task.Run(() => Foo(idx));
            TaskList.Add(fooWrappedInTask);
        }

        Task.WaitAll(TaskList.ToArray());
        Console.WriteLine("Finished waiting for all of the tasks: - Thread {0}", Thread.CurrentThread.ManagedThreadId);
    }
}

これをテストしたところ、目的のコンソール出力が生成されます。


ここでの主な違いは、Task.Runの代わりに を呼び出していることですTask.Factory.StartNew

Taskを返す があり、それが別の を返すことTaskさえありTaskます。これは、タスクの「チェーン」と考えることができます。

Task.RunTaskチェーンの最後のタスクを表すa を返します。それを待つときは、一連のタスクのすべてのリンクが完了するのを待っています。

比較するとTask.Factory.StartNew、チェーンの最初のリンクを表すタスクが返されます。それを待った後、待機するチェーンの残りが残ります。Taskこれは、が別のものではないものを返す場合には問題ありませんTask

于 2013-11-08T01:44:35.170 に答える