スレッドセーフなコレクション

2つのスレッドで1つのコレクションを操作することが良くあります。

たとえば、1つのスレッドで測定値をコレクションに追加し続ける。
もう1つのスレッドでコレクションから測定値を取り出し、画面表示したり、ファイル保存したり。

C#のList<T>などのコレクションクラスはスレッドセーフではないので、
複数スレッドで操作する場合、操作する前にLockを行います。
しかし、Lockをするのはいちいち面倒ですし、間違ってLockせずに使用する不安もあります。

.Net3.0からはSynchronizedCollectionクラスなどスレッドセーフなコレクションが追加されています。
このコレクションを使用すると、AddやRemoveなどの単独操作はスレッドセーフになります。
しかし、ForEachなどの複合操作はスレッドセーフになりません。ですので不安が残ります。

結局、SynchronizedCollectionを内包し、スレッドセーフな操作しか行えないクラスを作成するのが一番良いかと考えています。
実装可能な操作はかなり限定されます。
AddかEnqueue、Clear、DequeueAll(全ての要素を取得してクリアする)、ToList、Count
こんなところでしょうか。
キューの操作しかできないので、クラス名はThreadSafeQueueにします。
スレッド間での複数要素の受け渡し用と割り切れば、役に立つのではないかと思います。

なお、List<T>のようにインデックスによる取得操作は実装できません。
指定したインデックスの要素が別のスレッドでRemoveされている可能性があります。
Dequeueも実装できません。
Dequeueした時には要素が1つも無い可能性があります。
TryGetやTryDequeueにして取得できたがどうかも戻せば良いかも知れません。

コメントを残す