11

整数の列挙可能なコレクションを作成し、それを並行して処理する次のコード サンプルを検討してください。

using System.Collections.Generic;
using System.Threading.Tasks;

public class Program
{
    public static void Main()
    {
        Parallel.ForEach(CreateItems(100), item => ProcessItem(item));
    }

    private static IEnumerable<int> CreateItems(int count)
    {
        for (int i = 0; i < count; i++)
        {
            yield return i;
        }
    }

    private static void ProcessItem(int item)
    {
        // Do something
    }
}

Parallel.ForEach()それぞれによって生成されたワーカースレッドが異なるアイテムを取得することが保証されていますか、iそれとも必要なインクリメントとリターンに関するロックメカニズムですか?

4

2 に答える 2

12

Parallel.ForEach<TSource>が の場合、TSourceは独自の内部ロック メカニズムIEnumerable<T>を含むのパーティショナーを作成するため、イテレーターにスレッド セーフを実装する必要はありません。IEnumerable<T>

ワーカー スレッドが項目のチャンクを要求するたびに、パーティショナーは内部列挙子を作成します。

  1. 共有ロックを取得します
  2. ソース (残っていた場所から) を反復処理してアイテムのチャンクを取得し、アイテムをプライベート配列に保存します
  3. ロックを解放して、他のチャンク要求を実行できるようにします。
  4. プライベート配列からワーカー スレッドを提供します。

ご覧のとおりIEnumerable<T>、パーティショニングのための実行はシーケンシャル (共有ロック経由でアクセス) であり、パーティションは並列で処理されます。

于 2013-06-10T12:21:46.003 に答える
2

TPL と PLINQ は、パーティショナーの概念を使用します。

Partitioner<TSource>パーティショナーは、ソース シーケンスをいくつかの部分 (またはパーティション) に分割するために継承および機能するタイプです。組み込みのパーティショナーは、ソース シーケンスを重複しないパーティションに分割するように設計されています。

于 2013-06-10T10:49:56.977 に答える