parallel.foreachを解除しますか?


111

parallel.forループから抜け出すにはどうすればよいですか?

次のようなかなり複雑なステートメントがあります。

Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),
    new Action<ColorIndexHolder>((ColorIndexHolder Element) =>
    {
        if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I)
        {
            Found = true;
            break;
        }
    }));

並列クラスを使用すると、このプロセスを大幅に最適化できます。しかしながら; 並列ループを解除する方法がわかりませんか?break;文は、次の構文エラーがスローされます。

中断または継続する囲みループがない


1
ループのすべての並列インスタンスが同時に壊れると思いますか?
n8wrl 2012

回答:


185

次のParallelLoopState.Break方法を使用します。

 Parallel.ForEach(list,
    (i, state) =>
    {
       state.Break();
    });

またはあなたの場合:

Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),
    new Action<ColorIndexHolder, ParallelLoopState>((ColorIndexHolder Element, ParallelLoopState state) =>
    {
        if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I)
        {
            Found = true;
            state.Break();
        }
    }));

丁度。これを自分で投稿しようとしていました。
Mare Infinitus 2012

1
順次foreachループについて考えると、何らかの理由で中断の原因となった項目の前の項目が処理されることが保証されています。Parallel.ForEachの場合、アイテムの順序は必ずしもそれらが処理される順序である必要はありませんか?state.Break()を呼び出すものの前のIEnumerable <...>内のすべての項目が処理され、その後に来るものは処理されないことも保証されていますか?前者はなんとかして達成できたかもしれませんが、後者がどのようにして可能になるのかはまったくわかりません。
Hendrik Wiese 2013年

4
@Hendrikヴィーゼ:ドキュメントは言う:Calling the Break method informs the for operation that iterations after the current one don't have to execute. However, all iterations before the current one will still have to be executed if they haven't already.there is no guarantee that iterations after the current one will definitely not execute.
チューダー

2
したがって、state.Stop()以下にMike PerrenoudとMBentleyによって述べられているように、期待される結果を確実に達成するために、より適切です
xtreampb

44

これを行うには、ループ状態で渡されるParallel.Forまたはのオーバーロードを使用して呼び出しParallel.ForEach、次にParallelLoopState.Breakまたはを呼び出しParallelLoopState.Stopます。主な違いは、物事が壊れる速さです。を使用するとBreak()、ループは現在よりも前の「インデックス」を持つすべてのアイテムを処理します。を使用Stop()すると、できるだけ早く終了します。

詳細については、「方法:Parallel.Forループから停止または中断する」を参照してください。


3
+1、ここにいる私たちの何人かはまったく同じ答えを持っているように見えます:)-ああ、私はその他のコメントマンにあなたを呼び戻しました。
Mike Perrenoud 2012

この説明をありがとう。ブレークまたはストップのどちらが呼び出されたかを知っていますか?それは、現在実行中の反復が完了した場合ですか、それとも実行の途中で反復を停止した場合ですか?
CeejeeB 2013年

1
@CeejeeB現在実行中の操作が完了しました。
リードコプシー2013年

12

使用する必要があるのはAny、foreachループではなくです。

bool Found = ColorIndex.AsEnumerable().AsParallel()
    .Any(Element => Element.StartIndex <= I 
      && Element.StartIndex + Element.Length >= I);

Any 結果が真でなければならないことがわかるとすぐに停止するのに十分なほどスマートです。


10

LoopStateは確かに素晴らしい答えです。以前の回答には他にも多くのものがあり、回答を確認するのが困難であることがわかったので、簡単なケースを次に示します。

using System.Threading.Tasks;

Parallel.ForEach(SomeTable.Rows(), (row, loopState) =>
{
    if (row.Value == testValue)
    {
        loopState.Stop();  // Stop the ForEach!
    }       
    // else do some other stuff here.
});

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.