IEnumerable が実際にインデクサーを備えたものである場合 (つまりobj[1]
、アイテムを取得するために実行できる場合)、次のことができます。
var rangePartitioner = Partitioner.Create(0, source.Length);
Parallel.ForEach(rangePartitioner, (range, loopState) =>
{
// Loop over each range element without a delegate invocation.
for (int i = range.Item1; i < range.Item2; i++)
{
var item = source[i]
//Do work on item
}
});
ただし、それができない場合は、 から派生した新しいクラスを作成して、カスタム パーティショナーを作成する必要がありますSystem.Collections.Concurrent.Partitioner<TSource>
。その主題は SO 回答でカバーするには広すぎますが、開始するには MSDN のこのガイドを参照してください。
更新: .NET 4.5 の時点で、Partitioner.Create
データをバッファリングしないオーバーロードが追加されました。これは、範囲の最大サイズが 1 のカスタム パーティショナーを作成するのと同じ効果があります。一連の遅いアイテムが連続して不運になった場合、作業をキューに入れました。
var partitoner = Partitioner.Create(source, EnumerablePartitionerOptions.NoBuffering);
Parallel.ForEach(partitoner, item =>
{
//Do work
}