Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing IDisposable in a class exposing Begin/End methods

Tags:

c#

.net

dispose

Say I have a class that exposes BeginLongOperation() and EndLongOperation() methods with the standard Begin/End pattern, and implements IDisposable.

Is it my class's responsibility to handle a call to Dispose() between the calls to BeginLongOperation() and EndLongOperation()?

If so, what is the proper way to do this?

like image 295
Mills Avatar asked Jan 29 '13 06:01

Mills


2 Answers

Is it my class's responsibility to handle a call to Dispose() between the calls to BeginLongOperation() and EndLongOperation()?

No, it's the responsibility of the caller of your class to properly dispose it. This could be done in the EndLongOperation method. You cannot wrap the instance in a using statement because the BeginLongOperation method will return immediately.

Example with a WebClient:

var client = new WebClient();
client.DownloadStringCompleted += (sender, e) =>
{
    try
    {
        if (e.Error == null)
        {
            Console.WriteLine(e.Result);
        }
    }
    finally
    {
        ((WebClient)sender).Dispose();
    }
};
client.DownloadStringAsync(new Uri("http://www.google.com"));
like image 123
Darin Dimitrov Avatar answered Sep 20 '22 11:09

Darin Dimitrov


I assume that Begin/End methods are asynchronous. Or, that your objects can be manipulated from another thread.

First, you need to determine if you really need to dispose the instances of your class. If so, you need to design your Dispose() method (your class should implement IDisposable interface) in such way that it won't interfere with the long operation being executed. Well, it depends what policy you want to implement: do you want to wait for long operation to finish, or a call to Dispose() method should interrupt the long operation?

Normally you never call Dispose() method from your class' inside code, but indeed you need to protect the Dispose() call from unappropriate usage.

So I think that is YOUR responsability to protect your code against any possible scenarios, even against a (undesired) call between Begin and End.

LATER EDIT: of course, as other guys here told you, the responsability of the user of your class is to properly use it, BUT I would NOT rely on this. As you know, when the last reference to your object is gone, your object is subject to be garbage collected. This bad usage pattern could indeed determine a call to Dispose() between Start/End even in a non-async / single thread design.

like image 45
Adi Avatar answered Sep 21 '22 11:09

Adi