2010-03-30 19 views
7

Dado un objeto, ¿hay alguna forma de recibir una notificación de cuándo se recoge ese objeto?.NET: ¿Alguna manera de saber cuándo se elimina un objeto/se recoge basura?

Estoy jugando con los métodos de extensión C# se comportan un poco más como mixins (específicamente al agregar el registro). Entonces, básicamente, cada objeto obtiene un nuevo método Logger() que devuelve un ILog que se crea y almacena en caché dependiendo del objeto que es el objetivo del método de extensión.

Funciona bastante bien, la única preocupación es, obviamente, después de que un objeto desaparece su registrador puede permanecer por bastante tiempo. Por supuesto, podría configurar algún mecanismo periódico para barrer la memoria caché del logger y borrarla, pero preferiría configurar algo de notificación de Recolección de basura para saber cuándo el sistema ya no usa mis objetos.

¿Alguien sabe de una manera de hacer esto?

Respuesta

11

Creo que lo que generalmente se hace aquí es mantener una lista de WeakReferences. Con una referencia débil, puede saber si el objeto al que se refiere ha sido recolectado o no recolector de basura al marcar la propiedad IsAlive.

+1

+1, maldición, robó mi respuesta jaja – heisenberg

1

The destructor se llama durante GC.

+1

Eso es gracioso. Siempre los escuché referidos como "Finalizadores". ¿Ha cambiado la nomenclatura o me equivoqué todo este tiempo? –

+1

Creo que esto depende del idioma. Parece que en C#, * destructor * se refiere a la construcción del lenguaje que implementa * finalización *. Sin embargo, en C++/CLI, el constructo de lenguaje llamado * destructor * (por ejemplo, '~ class() {...}' implementa realmente la interfaz * IDispose *, mientras que hay una nueva construcción de lenguaje llamada * finalizer * (por ej. ! class() {...} 'que es lo mismo que * destructor * en C#. – stakx

+0

Sí, pero eso significa que tengo que crear un destructor que llame a algo como esto. ReleaseLogger(). No es una mala idea, pero es algo que preferiría evitar. –

3

En .NET 4.0, hay un tipo ConditionalWeakTable que se puede utilizar, aunque de manera un tanto incómoda, para solicitar una notificación cuando un objeto arbitrario puede ser finalizado. Si un ConditionalWeakTable contiene una entrada mapeando un objeto (digamos el 451er objeto creado) a otro objeto (digamos el 730o objeto creado), entonces mientras la entrada permanezca en la tabla, y existen referencias rooteadas tanto en la tabla como en el objeto # 451, la tabla se considerará una referencia rooteada al objeto n.º 730. Si no existe una referencia rooteada para el objeto n. ° 451, la tabla dejará de ser una referencia rooteada al objeto n. ° 730.

En consecuencia, si el objeto # 730 contiene una referencia a la tabla y al objeto # 730 existe fuera de la tabla, el objeto # 730 será elegible para finalización al mismo tiempo que el objeto # 451. Si el objeto n. ° 730 anula Finalize(), esa anulación se puede usar como notificación de que el objeto n. ° 451 es elegible para finalización.

Tenga en cuenta que el finalizador para el objeto n. ° 730 solo se activará una vez aunque el objeto n. ° 451 resure y se vuelva a registrar para la finalización. Sería posible escribir el código que dispararía la notificación en el momento en que el objeto # 451 realmente muera y se entierre, incluso si resucita varias veces primero, pero no hay una manera particularmente limpia de hacerlo.

+0

Sería genial tener una clase que maneje esto y abstraiga lo feo, proporcionando al cliente que llama una interfaz bonita, FWIW. Además, por lo que estoy leyendo, ¿parece que un objeto solo puede resucitar una vez? Es eso exacto?Fuente: http://www.philosophicalgeek.com/2014/08/20/short-vs-long-weak-references-and-object-resurrection/ –

Cuestiones relacionadas