4

次の場合:

BlockingCollection<MyObject> collection;

public class MyObject
{
   public async Task<ReturnObject> DoWork() 
   {       
      (...) 
      return await SomeIOWorkAsync();
   }
}

コレクション内のすべてのMyObjectですべてのDoWork()タスクを非同期で同時に(リターンオブジェクトをキャプチャしながら)実行するための正しい/最もパフォーマンスの高い方法は何ですか?)?

4

4 に答える 4

6

WhenAll 拡張メソッドを利用できます。

var combinedTask = await Task.WhenAll(collection.Select(x => x.DoWork());

すべてのタスクを同時に開始し、すべてが完了するのを待ちます。

于 2012-12-17T07:57:18.407 に答える
3

ThreadPool実行中のスレッドの数を管理しますが、それは非同期の s ではあまり役に立ちませんTask

そのため、他のものが必要です。ActionBlockこれを行う 1 つの方法は、TPL データフローを利用することです。

int limit = …;
IEnumerable<MyObject> collection = …;

var block = new ActionBlock<MyObject>(
    o => o.DoWork(),
    new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = limit });

foreach (var obj in collection)
    block.Post(o);

block.Complete();
await block.Completion;
于 2012-12-17T12:03:36.073 に答える
1

理想的には適切なスレッド制限を使用して、コレクション内のすべてのMyObjectで同時に(戻りオブジェクトをキャプチャしながら)すべてのDoWork()タスクを非同期で実行するための正しい/最もパフォーマンスの高い方法は何でしょうか。

これを行う最も簡単な方法は、Task.WhenAll次の方法です。

ReturnObject[] results = await Task.WhenAll(collection.Select(x => x.DoWork()));

これにより、コレクション内のDoWorkすべてが呼び出され、MyObjectsすべてが完了するのを待ちます。スレッドプールは、すべてのスロットルを適切に処理します。

すべてのアイテムが完了するのを待つのではなく、すべての個々のDoWork()リターンをすぐにキャプチャしたい場合、別の方法はありますか?

はい、 JonSkeetStephenToubによって説明された方法を使用できます。AsyncExライブラリ(NuGetから入手可能)にも同様のソリューションがあり、次のように使用できます。

// "tasks" is of type "Task<ReturnObject>[]"
var tasks = collection.Select(x => x.DoWork()).OrderByCompletion();
foreach (var task in tasks)
{
  var result = await task;
  ...
}
于 2012-12-17T14:56:22.907 に答える
0

私のコメントは少し不可解だったので、次の回答を追加します。

List<Task<ReturnObject>> workTasks =
  collection.Select( o => o.DoWork() ).ToList();

List<Task> resultTasks =
  workTasks.Select( o => o.ContinueWith( t =>
      {
        ReturnObject r = t.Result;
        // do something with the result
      },
      // if you want to run this on the UI thread
      TaskScheduler.FromCurrentSynchronizationContext()
    )
  )
  .ToList();

await Task.WhenAll( resultTasks );
于 2012-12-17T09:18:30.537 に答える