8

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?

Mills
  • 355
  • 3
  • 8

4 Answers4

4

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"));
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
1

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.

Community
  • 1
  • 1
Adi
  • 5,113
  • 6
  • 46
  • 59
0

You should not declare object of such class inside a using block but try to dispose it manually.

You can call dispose of such class inside EndLongOperation handler in the class which uses this object.

mihirj
  • 1,199
  • 9
  • 15
0

Idea behind the IDisposable is below and I think that answers your question also.

The primary use of this interface is to release unmanaged resources. The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. However, it is not possible to predict when garbage collection will occur. Furthermore, the garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams.

Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector. The consumer of an object can call this method when the object is no longer needed.

So its duty of developer who is using your class to call Dispose().

D J
  • 6,908
  • 13
  • 43
  • 75