2010-06-15 6 views
5

(1) He leído muchas preguntas sobre IDisposable donde las respuestas recomiendan no utilizar Finalize a menos que realmente lo necesite debido al tiempo de proceso involucrado.
Lo que no he visto es cuánto es este costo y con qué frecuencia se paga. ¿Cada milisegundo? ¿segundo? hora, día, etc.El costo de finalizar en .NET

(2) Además, me parece que Finalize es útil cuando no siempre se sabe si se puede eliminar un objeto. Por ejemplo, la clase de fuente de marco. Un control no puede deshacerse de él porque no sabe si la fuente está compartida. La fuente generalmente se crea en el momento del diseño, por lo que el usuario no sabrá cómo deshacerse de ella, por lo tanto, finalice las patadas para finalmente deshacerse de ella cuando no queden referencias. ¿Es esa una impresión correcta?

+4

Lea esto: http://msdn.microsoft.com/en-us/library/ms973837.aspx –

+0

Con respecto a la clase 'Font', en realidad se usa para dos propósitos muy diferentes en .net; encapsula un conjunto de información sobre una fuente (familia, tamaño, estilo, etc.) y también encapsula un objeto de búsqueda de GDI. La propiedad 'Font' de un control solo está interesada en la información anterior; a los controles no les importará si su propiedad 'Font' está configurada en una fuente que es' Dispose'd (¡incluso si el 'Dispose' ocurre antes de que se establezca la propiedad!) En consecuencia, si uno desea tener un campo que usará para establecer las propiedades de control de 'Fuente', se podría crear una 'Fuente' para ello y luego ... – supercat

+0

... inmediatamente 'Eliminarla '. Un patrón un tanto extraño, sin duda, pero fundamentalmente indicativo del hecho de que .net debería haber usado una clase 'FontInfo' o una estructura para los controles '' Fuente' propiedad. – supercat

Respuesta

7

El principal problema con finalizar es que bloquea la recogida de un objeto. En cambio, se llama al finalizador y el objeto se recoge "en la siguiente ejecución". Bueno, técnicamente IIRC el finalizador ejecuta una lista de objetos en un hilo separado. De todos modos, esto no es un problema "cada ms", más un "múltiples carreras GC necesarios para deshacerse de los objetos.

+0

Mejor explicación de lo que podría dar. – Meiscooldude

4

Finalizar es conceptualmente diferente a botar. Finalizar pueden los sólo recursos no administrados libres. Desechar puede liberar logrado . y los recursos no administrados deben utilizar cada uno según sea apropiado (Tenga en cuenta que una clase con un finalizador siempre debe aplicar IDisposable)

Desechar se debe llamar de forma explícita; Finalizar sólo puede ser llamado por el GC

actualización...: Ver mi publicación en el blog en How to Implement IDisposable and Finalizers: 3 Easy Rules.

+0

Eso no es del todo correcto. Debe mantener el finalizador corto, pero si necesita trabajar allí, puede hacerlo. (las rutinas de depuración vienen a la mente) – Spence

+1

Tenga en cuenta que no puede suponer que exista ningún objeto que no sea el objeto que se está finalizando. – Spence

+0

@Spence: su segundo comentario es por qué su primer comentario normalmente no es posible. ;) Hay un puñado de excepciones, como 'Console.WriteLine', pero como regla general, lo que yo llamo" lógica de apagado "solo es posible en' Dispose' y no en un Finalizer. –

0

Finalizar es extremadamente útil como una doble verificación. Si un bloqueo o el código incorrecto de una persona no descarta su objeto antes de que salga del alcance, garantice que sus recursos se liberarán en el finalizador.

Usted puede hacer un trabajo de pies elegante en su triturador llamando al GC.SuppressFinalize(this) que le permitirá escribir un método que funcione en ambas situaciones y le garantice que el código funcionará correctamente.

Incluso podría disparar una MDA si estuviera escribiendo un marco para recordar a las personas que deberían deshacerse de su objeto.

La penalización del finalizador es, básicamente, que termina empujando su objeto en la cola de nivel 2, que tarda más tiempo en ejecutarse. Si está utilizando objetos de manera consistente y están finalizando, esto podría generar una recolección de nivel 2 que se ejecuta con más frecuencia de la necesaria solo para ejecutar los subprocesos del finalizador.

1

Voy a responder a su segunda pregunta.

No, Finalize no debe utilizarse de esta manera. De hecho, con la excepción de solo unos pocos casos de margen, solo debe anular Finalize (o declarar un destructor en C#) si la clase contiene directamente recursos no administrados.

El problema que describió es de propiedad. El propietario de una clase IDisposable es responsable de su duración y la decisión de cuándo llamar al Dispose. Otras partes del código son libres de usar esa clase, pero como no pueden reclamar la propiedad, no deberían participar en la administración de la clase de esa clase.

Por desgracia, no estoy muy familiarizado con la clase Font ni cómo se podría relacionar con la situación que se fue el impulso para su pregunta, pero puedo hacer una declaración general que podrían aplicarse en su caso. Si su código no creó la instancia (a través del constructor) directamente, entonces su código no debería considerarse el propietario. En ese caso, puede asumir que la responsabilidad de la eliminación se deja a otra cosa.

Cuestiones relacionadas