「要素がランダムに選択される」場合、正確に何をしているのかわかりません。ただし、を使用する場合はParalle.ForEach()
、効率的にしようとするため、入力シーケンスを何らかの方法で分割します。入力シーケンスがの場合はIList<T>
範囲分割を使用し、そうでない場合はチャンク分割を使用します(PLINQのチャンク分割と範囲分割を参照)。
アイテムを順番に処理する場合は、カスタムパーティショナーParallel.ForEach()
を使用して構成できます。これにより、コレクションがサイズ1のチャンクに分割されます。
ただし、ここでは実際には必要ないためParallel.ForEach()
、おそらくより簡単な解決策は、アイテムを1つずつ処理する4つのタスクを作成することです。同期には、を使用できますBlockingCollection
。何かのようなもの:
public static class ParallelOrdered
{
public static void ForEach<T>(IEnumerable<T> collection, Action<T> action, int degreeOfParallelism)
{
var blockingCollection = new BlockingCollection<T>();
foreach (var item in collection)
blockingCollection.Add(item);
blockingCollection.CompleteAdding();
var tasks = new Task[degreeOfParallelism];
for (int i = 0; i < degreeOfParallelism; i++)
{
tasks[i] = Task.Factory.StartNew(
() =>
{
foreach (var item in blockingCollection.GetConsumingEnumerable())
action(item);
});
}
Task.WaitAll(tasks);
}
}