1

MWE は次のとおりです。

Func<Int32, Boolean> MyFunc = (s) => {
    var res = false;
    // Insert function logic to modify the value to res
    return res;
};
var Result = new List<Int32> ();
var LockObj = new Object ();
ParallelEnumerable.Range (1, 100000)
    .ForAll (s => {
        if (MyFunc (s)) {
            lock (LockObj) { // IS THIS NECESSARY?
                Result.Add (s);
            } // End lock
        }
    });

突き詰めるとこんな状況です。ParallelEnumerable ステートメントの実行が完了する前にクエリを実行しない場合、Result をロックする必要はないと考えるのは正しいですか?

注意:MWEは、次のように「Where」句で解決する方がよいことを知っています。

ParallelEnumerable.Range (1, 100000)
    .Where (s => MyFunc (s));

しかし、MWE で明らかにされていない理由により、これは実行できません。

編集

答えてくれたみんなありがとう。コメントもありがとうございます。Tung が見つけたエラーを修正しました。

4

4 に答える 4

4

はい、しなければなりませんlock。Parallel.For は への同時呼び出しを引き起こしますAdd()

余談ですが:

//var Result = new List<Int32> ();
var Result = new List<Int32> (100000);
ParallelEnumerable.Range (1, 100000)

これにより、はるかに効率的になります。成長が少ないということは、 での競合が少ないことも意味しlockます。

于 2012-05-01T07:16:23.303 に答える
3

汎用リストへの追加は、スレッドセーフではありません。ロックは 1 つの可能性です。また、.Net 4.0 で導入されたスレッドセーフ コレクション タイプの 1 つを使用することもできます。

詳細については、並列 For ループ - リストに追加するときの問題をご覧ください。

于 2012-05-01T07:12:57.853 に答える
2

既存の並列コレクションのいずれかを選択することで、多くの競合を排除できます。

ConcurrentBag<int> bag=new ConcurrentBag<int>();
ParallelEnumerable.Range(0,10000).ForAll(s => {if(MyFunc(s)) bag.Add(s);});
于 2012-05-01T08:25:40.980 に答える
0

Semaphore.it を使用すると、共有リソース (この場合は共通リスト) へのアクセスが管理されます。

于 2012-05-01T07:21:18.927 に答える