How to dispose asynchronously?

Auron picture Auron · Dec 30, 2008 · Viewed 19.3k times · Source

Let's say I have a class that implements the IDisposable interface. Something like this:

http://www.flickr.com/photos/garthof/3149605015/

MyClass uses some unmanaged resources, hence the Dispose() method from IDisposable releases those resources. MyClass should be used like this:

using ( MyClass myClass = new MyClass() ) {
    myClass.DoSomething();
}

Now, I want to implement a method that calls DoSomething() asynchronously. I add a new method to MyClass:

http://www.flickr.com/photos/garthof/3149605005/

Now, from the client side, MyClass should be used like this:

using ( MyClass myClass = new MyClass() ) {
    myClass.AsyncDoSomething();
}

However, if I don't do anything else, this could fail as the object myClass might be disposed before DoSomething() is called (and throw an unexpected ObjectDisposedException). So, the call to the Dispose() method (either implicit or explicit) should be delayed until the asynchronous call to DoSomething() is done.

I think the code in the Dispose() method should be executed in a asynchronous way, and only once all asynchronous calls are resolved. I'd like to know which could be the best way to accomplish this.

Thanks.

NOTE: For the sake of simplicity, I haven't entered in the details of how Dispose() method is implemented. In real life I usually follow the Dispose pattern.


UPDATE: Thank you so much for your responses. I appreciate your effort. As chakrit has commented, I need that multiple calls to the async DoSomething can be made. Ideally, something like this should work fine:

using ( MyClass myClass = new MyClass() ) {

    myClass.AsyncDoSomething();
    myClass.AsyncDoSomething();

}

I'll study the counting semaphore, it seems what I'm looking for. It could also be a design problem. If I find it convenient, I will share with you some bits of the real case and what MyClass really does.

Answer

Greg Beech picture Greg Beech · Dec 30, 2008

It looks like you're using the event-based async pattern (see here for more info about .NET async patterns) so what you'd typically have is an event on the class that fires when the async operation is completed named DoSomethingCompleted (note that AsyncDoSomething should really be called DoSomethingAsync to follow the pattern correctly). With this event exposed you could write:

var myClass = new MyClass();
myClass.DoSomethingCompleted += (sender, e) => myClass.Dispose();
myClass.DoSomethingAsync();

The other alternative is to use the IAsyncResult pattern, where you can pass a delegate that calls the dispose method to the AsyncCallback parameter (more info on this pattern is in the page above too). In this case you'd have BeginDoSomething and EndDoSomething methods instead of DoSomethingAsync, and would call it something like...

var myClass = new MyClass();
myClass.BeginDoSomething(
    asyncResult => {
                       using (myClass)
                       {
                           myClass.EndDoSomething(asyncResult);
                       }
                   },
    null);        

But whichever way you do it, you need a way for the caller to be notified that the async operation has completed so it can dispose of the object at the correct time.