2010-03-15 25 views
9

¿Cuáles son los métodos para destruir los objetos de Excel de interoperabilidad COM en C#, además de estos:¿Cómo puedo destruir objetos COM en C#?

object_instance = null; 
System.GC.collect(); 
& 
System.Runtime.InteropServices.Marshal.ReleaseComObject(object); 

Para sugerir técnicas sólo incorporado, no otras herramientas como bigcannon, etc.

+2

¿Por qué necesita hacerlo? En la mayoría de los casos, el marco debe ocuparse de esto por usted? – Paddy

+3

object_instance = null; no destruye el objeto por cierto. Ni siquiera garantiza que será basura (es decir, porque otra cosa aún podría contener una referencia) –

+0

Tengo un problema con mi programa de Excel donde el objeto no recuperado está causando regularmente, puede decir "centelleo", después de buscar una cadena – perilbrain

Respuesta

17

El truco es que si no ha omitido todas las referencias al objeto, incluso GC.Collect no lo destruirá.

La regla en C# (o .NET en general) es que no se puede destruir un objeto. Dispose() no lo hará. Un finalizador no lo hará (regla número 2, no use un finalizador a menos que sepa por qué lo necesita y nunca lo llame directamente).

Para .NET, estas son las cosas que hay que hacer:

  1. Si un objeto contiene referencias a objetos no administrados, implementar IDispose patrón. E implementarlo completamente; es más que solo proporcionar un método Dispose().
  2. La única razón para tener un finalizador es liberar objetos no administrados, y solo en el caso de que su objeto no se haya eliminado correctamente. Una vez que se invoque su método de eliminación, debe hacer la limpieza y luego "matar" el finalizador llamando a GC.SuppressFinalize.
  3. Si está utilizando un objeto que implementa un método Dispose(), llame a Dispose() cuando haya terminado con ese objeto. Las mejores prácticas es asignar ese objeto con un bloque de uso. Salir del bloque de uso llamará a Dispose() automáticamente.
  4. Cuando haya terminado con un objeto, suelte todas las referencias al objeto, incluidos los controladores de eventos, delegados, etc.
  5. Más allá de eso, confíe en el recolector de basura para hacer su trabajo. No te metas con el recolector de basura; es probable que empeore las cosas, a menos que realmente, realmente, realmente sepas lo que estás haciendo y por qué.
+0

+1 - ¡buena respuesta! Calificaría # 1 para incluir recursos. Si su clase contiene una referencia a un objeto gestionado que implementa IDispose, también desea implementar el Patrón de eliminación. En general, esa clase desechable representará un recurso externo limitado o costoso. – TrueWill

+0

@TrueWill, buen consejo. Gracias. –

+0

¿Qué pasa con Marshal.ReleaseComObject? –

15

El recolector de basura es el único mecanismo que puede destruir un objeto gestionado , pero por lo general no lo invocas explícitamente. Simplemente deja que haga lo suyo.

Al igual que nunca llevas tu propia basura al depósito, simplemente la dejas sentada en la esquina. Siempre es responsabilidad del hombre de basura.

Puede liberar las referencias a las cosas y limpiarlas con IDisposable, finalizadores y destructores pero no destruirlas.

Al usar System.GC, puede pedirle al basurero que haga las cosas antes - solicite una ejecución personalizada solo para usted - pero esto generalmente arruina su agenda y tiene mucha más basura que la suya, así que es no recomendado.

+0

(arregla el nombre de la interfaz - espero que no te importe) –

+0

No, pero yo estaba a mitad de la edición, lo destruí accidentalmente pero lo devolví. –

+0

hay pocos casos en los que necesita eliminar explícitamente el objeto ....... aunque no puedo mostrarle mi programa, pero puedo asegurarle que realmente necesito destruir el objeto ... – perilbrain

0

Si su objeto asigna recursos significativos, es mejor implementar IDisposable y llamar explícitamente a Dispose. Si no puede llamar a Dispose por algún motivo y su clase reserva memoria no administrada, puede usar GC.AddMemoryPressure (con un GC.RemoveMemoryPressure coincidente en el finalizador) para decirle al GC que su clase es más pesada de lo que parece, priorizándola para el anterior limpiar.

2

En su mayor parte, debe eliminar todas las referencias a un objeto. Solo entonces el recolector de basura lo verá y lo destruirá.

ser conscientes de ello:

object_instance = null; 

Todo esto hace es matar la referencia object_instance. Esto funciona si es la única referencia. Si hay otras referencias, entonces no se recopilará.

var skywalker = new Person(); 
var object_instance = skywalker; 

...

object_instance = null; 
//It's still alive and won't be collected because skywalker lives... 
0

Si realmente necesita para liberar explícitamente la memoria ocupada por un objeto, y está seguro de que va a elegir el momento para exterminar mejor que GC, entonces el La única opción razonable es asignarlo a la pila y dejarlo morir cuando regrese del método donde se asignó.

0

Si desea control para poder administrar los recursos del objeto, implemente la interfaz IDisposable.

http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

Si los recursos no son la razón por la que desea controlar de forma explícita la destrucción de objetos, no puedo comprender por qué quiere ese nivel de control ... ¿Utiliza la agrupación de objetos?