Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it necessary to call Dispose on a Semaphore?

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()
 }

is the above safe + clean? Will the both _sync get disposed and myclass be collected when all 100 threads have finished doing their async work?

If not, what's the best way to know when to call _sync.Dispose() ?

like image 698
Jamona Mican Avatar asked Nov 19 '12 11:11

Jamona Mican


2 Answers

Short answer: No, you don't need to call Dispose().

Long answer:

Though it is recommended to call Dispose() when you are finished using the Semaphore, the garbage collector will take care of the semaphore's resources sooner or later.

An explicit call to Dispose() will guarantee an early release of the associated resource, but it's only required if you are creating and forgetting a lot of Semaphore instance in a short amount of time.

And if you call Dispose(), it is perfectly fine to use a simple Dispose() call. You don't need to create a finalizer ~myclass() because that would just duplicate what's already done the Semaphore implementation.

like image 155
Armin Avatar answered Oct 19 '22 20:10

Armin


If a class implements IDisposable, you really should dispose of it correctly. It is not just about relying on the garbage collector, the disposable class could have open handles / COM objects that need to be correctly cleaned up that you cannot guarantee that the GC will handle.

Ideally you should make myclass implement IDisposable and clean up your disposable objects in the dispose method. If you truly cannot determine when to dispose your instance of myclass then you can implement logic in the destructor method for myclass to call the dispose method.

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);
    }
}
like image 45
Bob Vale Avatar answered Oct 19 '22 18:10

Bob Vale