スレッドセーフな配列(List,Dictionary,Queue,Stack)を作成する。(SyncRoot,Synchronized)ジェネリック版。

基本的に配列の操作はスレッドセーフではないので(あるスレッドが配列に追加・削除している途中で、別スレッドでFor Eachしたら正しく列挙できない)マルチスレッドで配列のデータを操作する場合は、同時に実行されないようにロックする必要があります。

ジェネリックな配列の型の場合、SyncRootプロパティ、Synchronizedメソッドがありましたがジェネリック型ではIntellisenseに表示されません。ですが、実装されていない訳ではなく、SyncRootの場合はICollectionインタフェースを通じて、Synchronizedメソッドの場合は非ジェネリック型の静的メソッドを通じて、スレッドセーフ化することが出来ます。

■lockステートメントによるスレッドセーフ化


using System;
using System.Collections;
using System.Collections.Generic;

namespace ThreadSafeCollection
{
class Program
{

static void Main(string[] args)
{

Queue SafeQueue = new Queue();

lock (((ICollection)SafeQueue).SyncRoot)
{
SafeQueue.Enqueue("AddObject");
}

}
}
}

■Synchronizedスタティックメソッドによるスレッドセーフ化
ジェネリック型には、Synchronizedメソッドはありません。

と、思っていましたが代替方法があるようです。gsf_zero1さんに教えてもらいました。

[C#] Synchronizedしたコレクションの操作 (Collection, Queue, Synchronized, IsSynchronized, lock, CopyTo)
http://d.hatena.ne.jp/gsf_zero1/20100107/p2

.Net 3.0 からは以下のクラスが使えるようです。

・SynchronizedCollection ジェネリック クラス
・SynchronizedKeyedCollection ジェネリック クラス
・SynchronizedReadOnlyCollection ジェネリック クラス

使用するにはSystem.ServiceModelアセンブリへの参照設定が必要です。


using System;
using System.Collections;
using System.Collections.Generic;

namespace ThreadSafeCollection
{
class Program
{
static void Main(string[] args)
{

SynchronizedCollection SafeList = new SynchronizedCollection;
SafeList.Add("Add Object");

}
}
}

SynchronizedCollectionは、型自体がスレッドセーフなのでSynchronizedメソッドを呼び出す必要はありません。

gsf_zero1さんの記事でありますが、For Eachなどの複合処理は保護されないのでlockステートメントによる同期が必要です。