2011-02-10 18 views

Respuesta

10

Hay dos maneras básicas que un temporizador se mantiene incluso si se le haga referencia no almacena una referencia alguna parte:

  • Mientras el temporizador está activada. Hay un System.Threading subyacente.Timer que realmente genera el evento. El CLR mantiene una lista de temporizadores activos, el objeto de delegado de devolución de llamada mantiene el temporizador al que se hace referencia.

  • Por el controlador de eventos transcurrido, si no es estático. Eso extiende la vida útil de la instancia de Timer a al menos la duración del objeto de clase que contiene el controlador de eventos de Elapsed.

No hay modo de falla aquí. La única forma posible de obtener una referencia para el temporizador es a través del argumento del controlador de eventos transcurrido argumento. Si desactiva el temporizador, entonces ya no hay forma de obtener una referencia, por lo que es apropiado que el objeto se recopile.

Una forma bastante clásica de tener problemas con este temporizador y perder eventos transcurridos es cuando la propiedad AutoReset se establece en falsa. Un problema muy desagradable es que cualquier excepción planteada en el controlador de eventos transcurrido se traga sin ningún diagnóstico. Lo cual evitará la llamada, tendrías que reiniciar el temporizador al final. Haga favor System.Threading.Timer, no tiene este problema.

+0

+1. ¿Sabes por qué un 'System.Threading.Timer' sin referencias puede ser 'GC'ed pero no' System.Timers.Timer'? –

+0

@Stephen, no estoy seguro de lo que quiere decir. Las mismas reglas, lista de temporizadores activos dentro del CLR, la devolución de llamada hace referencia al objeto de destino. Y un System.Timers.Timer * no recuperado * puede * ser recolectado si no está habilitado. –

+0

Mi 'Temporizador.Threading.Timer' periódico no referenciado está GCed, pero no es mi referencia, auto-reset 'System.Timers.Timer'. El controlador de eventos no hace referencia al temporizador. ¿Puedes confirmar? (.NET 4.0 Client) –

1

Sí. Timer se GC'd si no se hace referencia, incluso mientras se ejecuta.

El documentation dice:

El código contiene declaraciones de la variable contador de tiempo a nivel de clase y en el interior principal. Para ver cómo la recolección de basura agresiva puede afectar un temporizador que se declara dentro de un método de larga ejecución, puede comentar la declaración de nivel de clase y descomentar la variable local. Para evitar que se recopile el temporizador, elimine el comentario del método GC.KeepAlive al final de Main.

+2

No, esto se corrigió en .NET 2.0. Intentalo. –

+1

Luego los documentos necesitan reparación: http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx es aproximadamente 4.5 –

Cuestiones relacionadas