23

変更する要素を取得するためにreadメソッドとreadメソッドを使用するwriteメソッドでReaderWriterLockSlimを使用するクラスがあります。簡単な例は次のとおりです。

class FooLocker
{
    ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
    List<Foo> fooList = new List<Foo>();

    public void ChangeFoo(int index, string bar)
    {
        locker.EnterWriteLock();

        try
        {
            Foo foo = GetFoo(index);
            foo.Bar = bar;
        }
        finally
        {
            locker.ExitWriteLock();
        }
    }

    public Foo GetFoo(int index) 
    {
        locker.EnterReadLock(); //throws System.Threading.LockRecursionException

        try
        {
            return fooList[index];
        }
        finally
        {
            locker.ExitReadLock();
        }
    }

    //snipped code for adding instances etc.
}

上記のように、このコードは、読み取りロックに入ろうとしたときに書き込みロックがすでに保持されているため、LockRecursionException呼び出し時にをスローします。ChangeFoo()GetFoo()

ドキュメントを確認しました。これReaderWriterLockSlimを使用LockRecursionPolicy.SupportsRecursionして、上記を機能させることができます。ただし、ドキュメントでは、これを新しい開発には使用せず、既存のコードをアップグレードする場合にのみ使用することも推奨しています。

これを考えると、書き込みメソッドが読み取り専用メソッドを使用して変更が必要なものを取得できるという同じ結果を達成するためのベストプラクティスは何ですか?

4

1 に答える 1

38

クラスを公開メソッドとプライベート内部メソッドに分割できます。内部メソッドはフェッチなどのロジックを実行し、パブリックメソッドはロックを実行します。例:

class FooLocker 
{ 
    ReaderWriterLockSlim locker = new ReaderWriterLockSlim(); 
    List<Foo> fooList = new List<Foo>(); 


    public void ChangeFoo(int index, string bar) 
    { 
        locker.EnterWriteLock(); 

        try 
        { 
            Foo foo = UnsafeGetFoo(index); 
            foo.Bar = bar; 
        } 
        finally 
        { 
            locker.ExitWriteLock(); 
        } 
    } 

    public Foo GetFoo(int index)  
    { 
        locker.EnterReadLock();  

        try 
        { 
            return UnsafeGetFoo(index);
        } 
        finally 
        { 
            locker.ExitReadLock(); 
        } 
    } 

    private Foo UnsafeGetFoo(int index)
    {
        return fooList[index]; 
    }
} 
于 2012-03-28T08:59:04.290 に答える