10
class myclass 
{
    private Semaphore _sync;

    myclass ()
    {
          _sync = new Semaphore(1,1);
    }

    doasync()
    {
           _sync.WaitOne();
           //do some stuff
           _sync.Release();
    }
}


 somefunctionsomewhere() 
 {
     var myobject = new myclass();    
     //spawn 100 threads that all call myobject.doasync()
 }

上記は安全でクリーンですか?100 個のスレッドすべてが非同期処理を完了すると、_sync が破棄され、myclass が収集されますか?

そうでない場合、 _sync.Dispose() を呼び出すタイミングを知る最良の方法は何ですか?

4

2 に答える 2

11

簡単な答え: いいえ、Dispose() を呼び出す必要はありません。

長い答え:

セマフォの使用が終了したら Dispose() を呼び出すことをお勧めしますが、遅かれ早かれガベージ コレクタがセマフォのリソースを処理します。

Dispose() を明示的に呼び出すと、関連付けられたリソースの早期リリースが保証されますが、短時間で大量の Semaphore インスタンスを作成して忘れる場合にのみ必要です。

また、Dispose() を呼び出す場合は、単純な Dispose() 呼び出しを使用してもまったく問題ありません。ファイナライザーを作成する必要はありません~myclass()。これは、セマフォの実装で既に行われていることを複製するだけだからです。

于 2012-11-19T12:22:59.297 に答える
3

クラスが IDisposable を実装している場合は、正しく破棄する必要があります。ガベージ コレクターに頼るだけではありません。使い捨てクラスには、GC が処理することを保証できない、正しくクリーンアップする必要がある開いているハンドル/COM オブジェクトが含まれている可能性があります。

理想的には、myclassIDisposable を実装し、dispose メソッドで使い捨てオブジェクトをクリーンアップする必要があります。のインスタンスをいつ破棄するかを本当に判断できない場合は、破棄メソッドを呼び出す myclassためにデストラクタ メソッドにロジックを実装できます。myclass

public class myclass : IDisposable
   {
   private Semaphore _sync;

    myclass ()
    {
          _sync = new Semaphore(1,1);
    }

    doasync()
    {
           _sync.WaitOne();
           //do some stuff
           _sync.Release();
    }

    public void Dispose()
       Dispose(true);
       GC.SuppressFinalize(this);
    {

    protected void Dispose(bool isDisposing)
    {
       var sync=Interlocked.Exchange(ref _sync,null);
       if (sync !=null) sync.Dispose();
    }


    // This is for when you cannot determine when to dispose of your object
    void ~myclass() {
       Dispose(false);
    }
}
于 2012-11-19T12:04:15.220 に答える