3753817_s

C#でParallel.ForEachを使ってlistオブジェクトにaddでパラメータを追加してみたところ自分が想定していた動作が行われませんでした。

C#ってすごく便利だから、Parallel.ForEachを使ったら排他制御ぐらい勝手にしてくれるだろうとか思い込んでいたのですがそうではないみたいです。

なので今回、C#で排他制御を行う方法を調べたので忘備録として記録しておきます。



排他制御の行い方


C#も他の言語と同じようにマルチスレッドで動作させる場合には、排他制御の実装が必要になります。

排他制御を行わなかった場合、listに全ての変数が追加されないなど実際の処理内容が自分が想定しているものと違う風になってしまいます。

C#で排他制御を行うためにはlock構文を使えばいいみたいです。

lock構文の使い方ですが、以下のように使います。

lock(変数名)
        {
            処理1
            処理2
            …
        }

スレッドの実装も楽々なC#ですが、排他制御の実装まですぐにできるなんてさすがですね。



Parallel.ForEachでlistにaddするサンプルコード


Parallel.ForEachと先ほど紹介したlock構文を使って、listにデータをaddしていくsampleコードを以下に示します。

ちなみに今回のサンプルコードはスレッドなしで作成されたリストのようそを並列処理で別のリストに追加するというコードなのであまり意味がないコードですがサンプルなので気にしないでください。

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

class LockSample
{
    private static object lockTest = new object(); //ロック処理用オブジェクト
    public static void Main()
    {
        
        List<intnumList = new List<int>();
        List<intparralellList = new List<int>();

        for(int i=0i<100000; ++i){
            numList.Add(i);
        }

        // lock処理を使って追加する。
        Parallel.ForEach(numListnum =>
        {
            lock(lockTest)
            {
                parralellList.Add(num);
            }
        });

        Console.WriteLine("numList Count = " + numList.Count);
        Console.WriteLine("parralellList Count = " + parralellList.Count);
    }
}







まとめ


Parallel.ForEachでListオブジェクトを操作するには排他制御が必要でした。

C#では排他制御はlock構文で簡単に実装できるので、意図しない動作を起こさないために並列処理を行うときは排他制御を忘れないようにしましょう。