新しい記事を書く事で広告が消せます。
Exiting from Parallel Loops Early より
普通の for ループでは break と書けば簡単にループから抜け出せます。
んじゃ、Parallel.For や Parallel.ForEach では?とかそういう話。
で、上記の記事の前半では例外について書かれてます。
普通のループでは例外が発生しても問題ありませんし、ループの中だろうが外だろうが好きなところで catch できます。
しかし、Parallel ループではそうはいきません。
それぞれのイテレーション (ループの一回分のこと) はどのスレッドで実行されるかは不定ですから例外が外に伝わってくるとは限りませんし、どこかのイテレーションで例外が発生してもループが止まるとは限りません。
んじゃ、どうなるか?
上記の記事によるとどうやら
ということみたいです。
コードで書くと、
try { Parallel.For(0, N, i => { throw new Exception("例外"); }); } catch (AggregateException ex) { // ex.InnerExceptions.Count は 2 以上の可能性もある }
ということだと思います。
あと、一つのイテレーションが長い場合、他のイテレーションで例外が発生したかどうかは ParallelLoopState.IsExceptional で判断できるそうです。
Parallel.For / ForEach には body が Action<int, ParallelLoopState> となっているバージョンもあります。
それを使って以下のように書けるわけです。
Parallel.For(0, N, (i, loopState) => { // いろいろ処理 : if (loopState.IsExceptional) { // 他のイテレーションで例外が出てるので終了する return; } : // いろいろ処理 });
続いてループを抜ける件について。
これには ParallelLoopState.Stop() メソッドと Break() メソッドが使えます。
まずは、Stop() メソッドについて。
ということみたいです。
コードで書くと以下みたいな感じ。
Parallel.For(0, N, (i, loopState) => { : if (loopState.IsStopped) { // 他のイテレーションが Stop() を呼んだので終了する return; } : if (終了条件) { // もう終わる loopState.Stop(); return; } : });
続いて Break() です。
これは、http://msdn.microsoft.com/en-us/library/system.threading.parallelloopstate.break(VS.100).aspx を見ると、
ということみたいです。
ちょっとどう表現したらいいのかアレなんですが、要するに以下みたいなことだと思います。
0~1000 の Parallel.For ループがあったとします。
このうち、100番のイテレーションで Break() を呼んだとします。
すると 101~1000 のイテレーションは実行する必要が無いことが確定します。
また、この時点では ParallelLoopState.LowestBreakIteration に 100 がセットされます。
Parallel ループでは、イテレーションが並列で実行されるだけでなく、どういう順番で実行されるかも不定です。
ですから、0~99 のイテレーションに実行していないものがあるかもしれません。
もしあったらそれらのイテレーションを実行します。
そして、Break() を呼び出すより小さいイテレーションがあったらその数に ParallelLoopState.LowestBreakIteration が更新されます。
こうして Break() を呼び出す最小のイテレーションを求めて、その数が ParallelLoopState.LowestBreakIteration にセットされ Parallel ループが終了します。
どうだろ?
あってるかなぁ?
試す環境が無いのでちょっと自信が無いところもあるんですが、きっとこういうことだと思います。
Parallel Extensions なんてだいぶ前から CTP とか出てたし、最初はこういった解説ぐらいいくらでもあるんだろうと思ってたんですよね。
で、なにげにググってみたら ParallelLoopState だと 36件、ParallelLoopResult だと 6件という、びっくりするような結果で、もちろん日本語のページは一つも無し。
なので試す環境も無いくせに思わず書いてみましたw
あと、Parallel ループの中で気軽に使える ConcurrentQueue、ConcurrentStack なんていうスレッドセーフ版のコレクションも増えてるんですね。
http://msdn.microsoft.com/en-us/library/system.collections.concurrent(VS.100).aspx
これはなにげに便利そうだな。
FC2ブログ
名前: 青柳 臣一
(アオヤギ シンイチ)
住所: 大阪, 日本
仕事: ソフトウエアの開発
自転車: ANCHOR RFX8
好きなもの: C#,Silverlight,自転車,ロードバイク,ロードレース,アイマス,ニコマス,中村繪里子さん(えりりん),Blender,3DCG