2011-12-11 24 views
5

休止と停止(終了前)で最も効果的な方法は何でしょうか?parallel.foreach?Parallel.Foreach C#一時停止と停止機能?

Parallel.ForEach(list, (item) => 
{ 
    doStuff(item); 
}); 
+5

一時停止するのではなく、2を返しますか?なぜそれを一時停止したいですか? –

+0

一時停止は、もちろん可能なら追加したい機能です。私は、CPUとインターネット接続の両方に重いプログラムを書いていますので、一時停止すると悪くないかもしれません。私は停止機能を実装し、未完成の要素のリストを別のリストに保存し、次にそのリストを書き直して実行します。停止した場所から続行します。休止のようなもの。ありがとう。 – bbrez1

+0

答えの1つがあなたに解決策を与えた場合[あなたはその回答を受け入れたとマークする必要があります](http://stackoverflow.com/faq#howtoask)。 –

答えて

11

Damien_The_Unbeliverが良い方法を持っていますが、それはループを停止する外部プロセスがいくつかある場合のみです。通常のforまたはforeachループでbreakを使用するようにループを分割する場合は、ループ本体のパラメータの1つとしてParallelLoopStateを持つa overloadを使用する必要があります。 ParallelLoopStateには、あなたがやりたいことに関連する2つの機能、Stop()Break()があります。

機能Stop()はあなたがストップを(呼び出した後より多くの反復が実行される可能性を意味しているシステムの最も初期の利便で要素の処理を停止します)、あなたがで停止要素の前に来た要素も始まって​​いることを保証するものではありませんプロセスへ。

機能Break()行いまったく同じStop()としてしかし、それはまた、あなたが上Break()と呼ばれる項目の前に来たIEnumerableのすべての要素を評価します。これは、要素がどのような順序で処理されるか気にしないときに便利ですが、停止した点まですべての要素を処理する必要があります。

foreachから返されたParallelLoopResultを調べて、foreachが早期に停止したかどうかを確認し、Break()を使用した場合は、処理された番号が最も小さい項目を確認してください。ここで

Parallel.ForEach(list, (item, loopState) => 
    { 
     bool endEarly = doStuff(item); 
     if(endEarly) 
     { 
      loopState.Break(); 
     } 
    } 
    ); 
//Equivalent to the following non parallel version, except that if doStuff ends early 
// it may or may not processed some items in the list after the break. 
foreach(var item in list) 
{ 
    bool endEarly = doStuff(item); 
    if(endEarly) 
    { 
     break; 
    } 
} 

どんなにそれは常に答えとして2が返されます作業を分割する方法

static bool[] list = new int[]{false, false, true, false, true, false}; 

long LowestElementTrue() 
{ 
    ParallelLoopResult result = Parallel.ForEach(list, (element, loopState) => 
    { 
     if(element) 
      loopState.Break(); 
    } 
    if(result.LowestBreakIteration.IsNull) 
     return -1; 
    else 
     return result.LowestBreakIteration.Value; 
} 

より実用的な例ではありません。

プロセッサがこれを処理するために2つのスレッドをディスパッチした場合、最初のスレッドは要素0-2を処理し、2番目のスレッドは要素3-5を処理します。今、最も低いインデックスブレークから呼び出された

 
Thread 1:    Thread 2 
0, False, continue next 3, False, continue next 
1, False, continue next 4, True, Break 
2, True, Break   5, Don't process Broke 

はそうParallelLoopResult.LowestBreakIteration、無関係のスレッドが、それは常に2

ここ数まで処理するよう分割する方法を2たびに返されます2でしたStopがどのように使用されるかの例。

static bool[] list = new int[]{false, false, true, false, true, false}; 

long FirstElementFoundTrue() 
{ 
    long currentIndex = -1; 
    ParallelLoopResult result = Parallel.ForEach(list, (element, loopState, index) => 
    { 
     if(element) 
     { 
      loopState.Stop(); 

      //index is a 64 bit number, to make it a atomic write 
      // on 32 bit machines you must either: 
      // 1. Target 64 bit only and not allow 32 bit machines. 
      // 2. Cast the number to 32 bit. 
      // 3. Use one of the Interlocked methods. 
      Interlocked.Exchange (ref currentIndex , index); 
     } 
    } 
    return currentIndex; 
} 

作品をどのように分割するかに応じて、答えとして2または4が返されます。

プロセッサがこれを処理するために2つのスレッドをディスパッチした場合、最初のスレッドは要素0-2を処理し、2番目のスレッドは要素3-5を処理します。

 
Thread 1:     Thread 2 
0, False, continue next 3, False, continue next 
1, False, continue next 4, True, Stop 
2, Don't process, Stopped 5, Don't process, Stopped 

この場合、回答として4が返されます。同じプロセスを見ることができますが、0-2と3-5の代わりに他のすべての要素を処理する場合もあります。

 
Thread 1:     Thread 2 
0, False, continue next  1, False, continue next 
2, True, Stop    3, False, continue next 
4, Don't process, Stopped 5, Don't process, Stopped 

今回は4

2

Parallel.ForEachを停止することができるように、あなたはParallelOptionsパラメータを受け入れるオーバーロードのいずれかを使用し、それらのオプションでCancellationTokenを含めることができます。

詳細はCancellationを参照してください。

の場合、を一時停止すると、なぜそれをやりたいのかとは思えません。 Barrier(複数のスレッド間の作業を調整するために使用されています。たとえば、パートBを続ける前にパートAを完了する必要がある場合など)、Parallel.ForEachで使用するとは思わないでしょう。参加者の数は分かりません。

関連する問題