-1

アイテムのコレクションを保持するオブジェクトがあります。AddItem メソッドを使用してコレクションにアイテムを追加し、コレクション内のすべてのアイテムを調べたいと考えています。私のオブジェクトはスレッドセーフでなければなりません。適切な同期を保証するために ReaderWriterLockSlim を使用しています。GoThroughAllItems メソッドを同期するにはどうすればよいですか? 全体の期間全体にわたって大きな ReadLock を開始する必要がありますが、これは非常に長くなる可能性があります。それとも、コレクションからフェッチされた各アイテムのロックを解放し、次のアイテムのために再度ロックを取得する必要がありますか?

サンプルコードは次のとおりです。

プライベート ReaderWriterLockSlim @lock = new ReaderWriterLockSlim();
プライベート リスト項目 = 新しいリスト();

public void AddItem(項目項目)
{
    this.@lock.EnterWriteLock();

    試す
    {
        //アイテムを処理してコレクションに追加する
        this.items.Add(アイテム);
    }
    最後に
    {
        this.@lock.ExitWriteLock();
    }
}

public void GoThroughAllItems()
{
    this.@lock.EnterReadLock();

    試す
    {
        foreach (this.Items 内の Item アイテム)
        {
#if オプション 2
            this.@lock.ExitReadLock();
#endif

            //アイテムの処理。時間がかかる場合があります

#if オプション 2
            this.@lock.EnterReadLock();
#endif
        }
    }

#if オプション 2
    キャッチ
#endif
#if オプション 1
    最後に
#endif
    {
        this.@lock.ExitReadLock();
    }
}
4

2 に答える 2

0

ここでの最善の方法は、コレクションのコピーを作成してから、それを反復処理することです。かなりのメモリ オーバーヘッドがあります (ただし、すぐにリリースされます)。

擬似コード:

read lock
   foreach oldColl
      populate newColl
exit lock

   foreach newColl
      do things

foreach ではコレクションの変更が許可されていないため、他のスレッドがコレクションを変更する可能性があり、エラーが発生する可能性があるため、アイテムごとにロックを使用するコードは機能しません。

于 2010-09-10T11:25:42.333 に答える
0

複数のスレッドが読み取りブロックで許可されているため、 foreach の周りの読み取り領域で最初のオプションを選択するだけです。かなり遅いことは問題ではありません。一方、排他的書き込み操作は非常に高速です。それで、それは良い解決策になるはずです。

于 2010-09-10T11:59:02.550 に答える