1. ホーム
  2. c#

[解決済み] タスクの並列実行

2022-02-09 13:23:17

質問事項

OK、基本的に私はタスクの束(10)があり、それらをすべて同時に開始し、それらが完了するのを待ちたいと思います。完了したら、他のタスクを実行したいのです。このことについて多くのリソースを読みましたが、私の特定のケースではうまくいきません...。

現在、私が持っているものは以下のとおりです(コードは簡略化しています)。

public async Task RunTasks()
{
    var tasks = new List<Task>
    {
        new Task(async () => await DoWork()),
        //and so on with the other 9 similar tasks
    }


    Parallel.ForEach(tasks, task =>
    {
        task.Start();
    });

    Task.WhenAll(tasks).ContinueWith(done =>
    {
        //Run the other tasks
    });
}

//This function perform some I/O operations
public async Task DoWork()
{
    var results = await GetDataFromDatabaseAsync();
    foreach (var result in results)
    {
        await ReadFromNetwork(result.Url);
    }
}

そこで問題なのは、タスクの完了を待つために WhenAll の呼び出しは、どのタスクも完了していないにもかかわらず、すべてのタスクが終わったと教えてくれます。試しに Console.WriteLine の中に、私の foreach で、継続タスクを入力したところ、以前の Task というように、まだ終わっていないものがあります。

私はここで何を間違えているのでしょうか?

どうすればいいですか?

を使うことはほとんどありません。 Task コンストラクタを直接使用します。あなたの場合、そのタスクは、あなたが待つことができない実際のタスクを起動するだけです。

を呼び出すだけでよい。 DoWork で、タスクを取得し、それをリストに格納して、すべてのタスクが完了するのを待ちます。意味するところは

tasks.Add(DoWork());
// ...
await Task.WhenAll(tasks);

しかし、asyncメソッドは、未完了のタスクの最初のawaitに到達するまで同期的に実行されます。もしその部分に時間がかかりすぎるのが気になるのであれば Task.Run にオフロードし、別の ThreadPool スレッドに格納し その タスクをリストに追加します。

tasks.Add(Task.Run(() => DoWork()));
// ...
await Task.WhenAll(tasks);