2010-08-11 29 views
47

Duplicar posibles:
How does one tell if an IDisposable object reference is disposed?Cómo comprobar si el objeto se ha dispuesto en C#

¿Hay un método para comprobar si el objeto se ha dispuesto diferentes entonces

try 
{ 
    myObj.CallRandomMethod(); 
} catch (ObjectDisposedException e) 
{ 
    // now I know object has been disposed 
} 

En mi caso estoy usando la clase TcpClient que tiene el método Close() que descarta objeto y esto puede suceder en una pieza de código que no tengo control. En este caso, me gustaría tener una mejor solución que atrapar la excepción.

+3

http: // stackoverflow.com/questions/192206/how-do-one-tell-if-an-idisposable-object-reference-is-disposed – w69rdy

+0

Sabía que este problema en general es demasiado común para no tener preguntas y respuestas en stackoverflow, pero no pude buscarlo. – jethro

Respuesta

29

Una buena manera es derivar de TcpClient y reemplazar el método de disposición (bool):

class MyClient : TcpClient { 
    public bool IsDead { get; set; } 
    protected override void Dispose(bool disposing) { 
     IsDead = true; 
     base.Dispose(disposing); 
    } 
} 

que ganó No funciona si el otro código creó la instancia. Entonces tendrás que hacer algo desesperado como usar Reflection para obtener el valor del miembro privado m_CleanedUp. O atrapa la excepción.

Francamente, ninguno es probable que llegue a buen final. Realmente hizo desea escribir en el puerto TCP. Pero no lo hará, ese código erróneo que no puede controlar ahora tiene el control del código. Has aumentado el impacto del error. Hablar con el propietario de ese código y trabajar en algo es de lejos la mejor solución.

14

Si no está seguro de si el objeto ha sido eliminado o no, debe llamar al método Dispose en lugar de a métodos como Close. Si bien el marco no garantiza que el método Dispose debe ejecutarse sin excepciones, incluso si el objeto se había eliminado previamente, es un patrón común y, a mi conocimiento, implementado en todos los objetos desechables en el marco.

El patrón típico de Dispose, según Microsoft:

public void Dispose() 
{ 
    Dispose(true); 

    // Use SupressFinalize in case a subclass 
    // of this type implements a finalizer. 
    GC.SuppressFinalize(this);  
} 

protected virtual void Dispose(bool disposing) 
{ 
    // If you need thread safety, use a lock around these 
    // operations, as well as in your methods that use the resource. 
    if (!_disposed) 
    { 
     if (disposing) { 
      if (_resource != null) 
       _resource.Dispose(); 
       Console.WriteLine("Object disposed."); 
     } 

     // Indicate that the instance has been disposed. 
     _resource = null; 
     _disposed = true; 
    } 
} 

Aviso el cheque en _disposed. Si tuviera que llamar a un método Dispose que implementa este patrón, puede llamar a Dispose tantas veces como desee sin tocar las excepciones.

+2

Esto no es útil. El miembro es privado. –

+0

Lo siento, es posible que haya leído mal tu pregunta. ¿Está buscando detectar si un objeto está dispuesto por otros motivos que no sean "¿debería disponer de este objeto"? Si es así, ¿por qué? Tener un código desconocido potencialmente eliminar objetos parece un diseño con fugas. –

+2

Si bien el framework en sí no da ninguna garantía, la documentación para 'IDisposable' dice esto: *" Si el método 'Dispose' de un objeto se llama más de una vez, el objeto debe ignorar todas las llamadas después del primero. no lanzar una excepción si su método 'Dispose' se llama varias veces. Los métodos de instancia distintos de 'Dispose' pueden arrojar una 'ObjectDisposedException' cuando los recursos ya están eliminados." * http://msdn.microsoft.com/en-us/ library/system.disponible.dispose.aspx – LukeH

15

La solución confiable es capturar ObjectDisposedException.

La solución para escribir su implementación anulada del método Dispose no funciona, ya que hay una condición de carrera entre el hilo que llama al método Dispose y el que accede al objeto: después de haber verificado la hipotética propiedad IsDisposed, el objeto podría estar realmente dispuesto, arrojando la excepción de todos modos.

Otro enfoque podría estar exponiendo un evento hipotético Disposed (como this), que se utiliza para notificar sobre el objeto de eliminación a cada objeto interesado, pero esto podría ser difícil de planificar dependiendo del diseño del software.

Cuestiones relacionadas