2

クラスがありMyClassます。このクラスにはフィールドがあります:(public ReaderWriterLockSlim rw;より簡単なサンプルコードの場合はpublic)。多くのスレッドは、など MyClassを使用してデータを読み取ることができます。rw.EnterReadLock

IDisposableまた、私はインターフェース を実装しました:

private void Dispose (bool pDisposing)
{
    {
        if (pDisposing) // release managed resources
        {
            if (rw != null)
            {
                rwLockSlim.Dispose ();
                rwLockSlim = null;
            }
        }

        //--- release unmanaged resources
        // some code...
        isDisposed = true; // ...
    }
}

ご覧のとおり、問題は、myClassオブジェクトでMyClass2番目のスレッドが呼び出されたときに1つのスレッドが使用されている場合です。DisposeReaderWriterLockSlimを破棄すると、アプリケーションがクラッシュするため、破棄できません。では、管理対象リソースを解放する行を削除する必要がありますか?とにかく、ReaderWriterLockSlimは近い将来GCによって収集されますよね?(しかし、このクラスのリソースは高価ですか?)
たぶん、Dispose metodなどにlock(syncObject)を追加する必要がありますか?

編集:AllocHGlobalも扱っているので、すべてのスレッドがへの読み取り/書き込みを停止するまで待つ必要がありmyClassます。

別の視点:

public MyClass : IDisposable
{
            public void EnterReadLock (); // calls rwLockSlim.EnterReadLock,  
                                          // if object is disposed throws Exception

            public void ExitReadLock ();  // same as above

            public void Dispose ();       // wait until all threads exit from locks,
                                          // frees unamanged resources, mark class as disposed
}
4

1 に答える 1

1

これは最良の答えではないかもしれませんが、むしろ観察といくつかの考えです。

コードを簡素化できますか? つまり、特定の同時実行条件で型が例外をスローしても、他の型は気にするべきではありません。これをどのようにテストしますか?パブリック ロック オブジェクトは悪です。不可解なバグを解明するために何ヶ月も費やしたくない場合を除き、非公開にする必要があります。

dispose メソッドが呼び出された場合、他のオブジェクトがこのオブジェクトを使用してはならないことを意味します。つまり、dispose メソッドを呼び出す前に、まずすべてのスレッドがオブジェクトの処理を終了したことを確認する必要があります。

提案

  • ロックを非公開にする
  • Dispose を呼び出す前に、すべてのスレッドが終了していることを確認してください
  • 安全な動作のためにタイムアウトを追加する
  • 静的ロック オブジェクトの使用を検討する
  • ReaderWriterLockSlim はリソースが高価ではありません (アプリケーションで気にする必要がある点まで)
  • クラスで使い捨てリソースを使用する場合は、通常、IDisposable を実装し、破棄する必要があるメンバーを破棄することをお勧めします。
  • Dispose メソッドにロックを追加しないでください。単純にする必要があります。これにより、不快なバグが発生する可能性があります。Dispose を手動で呼び出すのを忘れると、GC によって非決定論的に呼び出されるため (Dispose を呼び出すために追加する必要があるフィニライザーを介して)
  • 正しいアプローチは、すべてのスレッドが完了するまで待機し、オブジェクトを破棄することです
于 2013-02-03T11:09:40.340 に答える