method - ¿Los finalizadores de.net son siempre ejecutados?
finalize c# (2)
Los finalizadores pueden nunca ser ejecutados, como explica Raymond Chen . Es gracioso que esta pregunta se haga durante su semana anual de CLR, solo dos días después de que la explicara :)
Para los perezosos, la conclusión (o mejor dicho, una) es:
Un programa escrito correctamente no puede asumir que los finalizadores se ejecutarán alguna vez.
Si se está preguntando si puede confiar en los finalizadores, esto es todo lo que tiene que saber: no confíe en los finalizadores.
Como Raymond Chen también afirma en el artículo vinculado:
Los finalizadores son una red de seguridad, no un medio principal para la recuperación de recursos.
Si está buscando cómo liberar recursos, eche un vistazo al patrón Desechable.
Un finalizador no puede ejecutarse, por ejemplo, si:
- Otro finalizador lanza una excepción.
- Otro finalizador toma más de 2 segundos.
- Todos los finalizadores juntos toman más de 40 segundos.
- Un dominio de aplicación se bloquea o se descarga (aunque puede evitarlo con un finalizador crítico (CriticalFinalizerObject, SafeHandle o algo así)
- No se produce recolección de basura
- El proceso se bloquea
(Nota: los valores de tiempo pueden haber cambiado con el tiempo, pero ciertamente fueron ciertos hace algún tiempo ).
Supongo que hay muchas más cosas que pueden hacer que los finalizadores nunca se ejecuten. La conclusión es, aparte de la cita del Sr. Chen, que los finalizadores son una red de seguridad que disminuye el impacto de los errores , porque, por ejemplo, los recursos se liberan en algún momento , lo cual es mejor que nunca , si se olvida de hacerlo explícitamente.
¿Se garantiza que los finalizadores se ejecutarán en .NET en algún momento (cortes de energía de repuesto y similares)? Sé cómo funciona GC y que no es determinista cuándo se ejecutarán exactamente.
(La búsqueda no mostró buenas respuestas, así que estoy agregando esta pregunta con la gran expectativa de una combinación con las respuestas reales que no son tan fáciles de descubrir. Aparte de eso, ya conozco la respuesta y voy a agregar después de unos días en caso de que nadie lo haya mencionado.
Si un finalizador lanza una excepción, otros finalizadores no se ejecutarán.
También puede suprimir los finalizadores si llama a SuppressFinalizer
en el objeto.
Desde MSDN (Object.Finalize):
Es posible que el método Finalizar no se ejecute hasta el final o no se ejecute en absoluto en las siguientes circunstancias excepcionales:
- Otro bloque finalizador indefinidamente (entra en un bucle infinito, intenta obtener un bloqueo que nunca puede obtener y así sucesivamente). Debido a que el tiempo de ejecución intenta ejecutar los finalizadores hasta su finalización, es posible que no se llame a otros finalizadores si el finalizador se bloquea indefinidamente.
- El proceso termina sin dar al runtime la oportunidad de limpiar. En este caso, la primera notificación del tiempo de ejecución de la terminación del proceso es una notificación DLL_PROCESS_DETACH.