How to find out an object has disposed?

26,206

Solution 1

Well, according to Reflector, CancellationTokenSource has an internal IsDisposed method that could've told you, but since it's internal, you're not supposed to call it.

In any case, if one thread yanks out data structures and objects other threads depend on, then don't do that. Fix your code and leave those objects live for the duration of their need.

In other words, wait for those other threads to finish needing the CancellationTokenSource before you dispose of it.

Solution 2

The proper course of action would be for the creators of some Disposable objects to go slightly against Microsoft's "rule" that performing any action on a disposed object should throw an exception, and instead follow the more general rule that an exception should be thrown any time a method's post-conditions can't be met. If the purpose of a Cancel method is to ensure that nobody will continue to regard a job as being live, and even before the Cancel method is called everyone regards the job as being dead, then the post-condition for the method is satisfied regardless of whether the object is disposed.

Generally, code outside a well-designed object shouldn't need to query whether it's been disposed, except possibly to assert that it has been. Instead, the object itself should provide methods whose meaning on a disposed object would be clear and unambiguous. Those methods might internally use an IsDisposed flag, but would have to use whatever locking was necessary to prevent race conditions. In general, the pattern

  if (!myThing.isDisposed) 
    myThing.DoSomething();

is an indication that myThing should really support a DoSomethingIfNotDisposed method (possibly called TryDoSomething). If you can't do that, my inclination might be to write your own DoSomethingIfNotDisposed extension method and use a Try/Catch to stifle an ObjectDisposedException (or whatever particular exception the object would throw).

Solution 3

Inherit your class and add the property:

class MyCancellationTokenSource: CancellationTokenSource
{
    public bool MyIsDisposed { get; private set; }
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        MyIsDisposed = true;
     }
}

Solution 4

check if the object is disposed before using it.

Still not the best design pattern. however here is what I use do determine if an object is disposed.

if (!object.IsDisposed) object.DoSomething();

or

public string DoSomething()
{
    if (this.IsDisposed) return null;
}

if that does not work, you may try adding an IsDisposed flag and overriding the dispose method. And setting that to true in your own code.

Share:
26,206
Xaqron
Author by

Xaqron

Physician

Updated on November 03, 2020

Comments

  • Xaqron
    Xaqron over 3 years

    I have a multi-threaded application and a CancellationToken is used as a shared object. Every thread can trigger it to tell the other threads the job is cancelled. Then one thread does the clean-up and disposes every object like this CancellationToken. Then if a thread tries to use it, an exception is raised:

    The CancellationTokenSource has been disposed.

    How can I find out an object is disposed before using it?

  • Xaqron
    Xaqron about 13 years
    I have one but the problem is race condition. Maybe a wait handle solve the problem.
  • supercat
    supercat about 13 years
    @Xaqron: If the class were properly designed, its Cancel method would simply do nothing if it has already been disposed (if it couldn't always avoid doing something that might cause an exception, it should stifle the exception within itself).
  • Vladyslav Tsvek
    Vladyslav Tsvek about 5 years
    CancellationTokenSource can't be inherited. It is a sealed class
  • Dominic Jonas
    Dominic Jonas over 3 years
  • Felix K.
    Felix K. over 2 years
    In general i agree but there are scenarios where this would lead to a lot additional code, cancelling should be possible without causing a exception. I currently work on a application where i either use a different mechanism to cancel tasks ( Which would be bad as part of it might become a public API ) or using the workaround to catch said exceptions.
  • Kim Homann
    Kim Homann about 2 years
    It was a sealed class in .NET Framework 4.0, but not anymore in .NET Framework 4.5+