visual tiempo tick reloj metodo interval ejemplos ejecutar cronometro con cierto cada c# .net garbage-collection reference timer

tiempo - En C#, ¿dónde debo guardar la referencia de mi temporizador?



timer.interval c# (3)

Creo que está bien mantener es un campo privado estático de su clase.

Mantendría esta referencia como un campo estático en lugar de jugar con el recolector de basura.

La documentación de System.Threading.Timer dice que debo mantener una referencia en vivo para evitar que se recolecte basura. Pero, ¿dónde debería hacer eso? Mi main es muy simple que no sé dónde guardar la referencia:

class Program { static void Main() { new System.Threading.Thread(myThreadStart).Start(); new System.Threading.Timer(myTimerCallback, new MyStateObject(), 0, 5000); } }

Pensé en mantener la referencia en un campo static en la clase Program , suponiendo que static campos static no se recopilan hasta el final de la aplicación. Pero no estoy seguro de que esta sea la mejor manera de hacerlo, así que agradecería su consejo.


EDITAR: Mi respuesta original es basura. Realmente basura. Lo he guardado aquí para explicar por qué es basura, está en los comentarios, pero se han eliminado con la respuesta.

GC.KeepAlive solo se asegura de que una referencia se trate como una raíz hasta después de la llamada. En el código en la parte inferior de esta respuesta, el método GC.KeepAlive sería llamado inmediatamente, y luego el temporizador seguiría siendo elegible para la recolección de basura. Como el subproceso recién creado es un subproceso en primer plano, la aplicación se ejecutará mientras esté activo (mientras que el temporizador utiliza un subproceso en segundo plano, que no impide la salida del programa). Esto significa que el método Principal se cierra, pero la aplicación necesita seguir ejecutándose.

Podría decirse que una solución más simple sería ejecutar myThreadStart en el hilo principal, en lugar de crear uno nuevo y luego dejar que el hilo principal muera. En otras palabras, una solución simple sería:

using System.Threading; class Program { static void Main() { Timer timer = new Timer(myTimerCallback, new MyStateObject(), 0, 5000); myThreadStart(); GC.KeepAlive(timer); } }

Supongo que el código real es más complicado, en cuyo caso usar la variable estática privada como se sugiere en otras respuestas es probablemente el camino a seguir. Sin embargo, realmente dependerá del uso. Personalmente prefiero no crear un campo estático solo para evitar que se recopile algo si hay una alternativa (como la anterior), pero a veces es prácticamente la única forma de hacerlo.

Respuesta original (mala):

Si realmente desea asignarlo en Main, puede usar GC.KeepAlive :

using System.Threading; class Program { static void Main() { new Thread(myThreadStart).Start(); Timer timer = new Timer(myTimerCallback, new MyStateObject(), 0, 5000); GC.KeepAlive(timer); } }


Si su Timer es un objeto a nivel de aplicación, no tiene nada de malo convertirlo en un miembro estático privado de su clase principal. Eso es lo que haría, de todos modos.