¿Pueden los Timers obtener basura automáticamente?

Cuando utiliza un Timer o un Thread que se ejecutará durante toda la vida útil del progtwig, ¿necesita mantener una referencia a ellos para evitar que se recoja basura?

Por favor, deje de lado el hecho de que el progtwig a continuación podría tener el timer como una variable estática en la clase, esto es solo un ejemplo de juguete para mostrar el problema.

 public class Program { static void Main(string[] args) { CreateTimer(); Console.ReadLine(); } private static void CreateTimer() { var program = new Program(); var timer = new Timer(); timer.Elapsed += program.TimerElapsed; timer.Interval = 30000; timer.AutoReset = false; timer.Enabled = true; } private void TimerElapsed(object sender, ElapsedEventArgs e) { var timerCast = (Timer)sender; Console.WriteLine("Timer fired at in thread {0}", GetCurrentThreadId()); timerCast.Enabled = true; } ~Program() { Console.WriteLine("Program Finalized"); } [DllImport("kernel32.dll")] static extern uint GetCurrentThreadId(); } 

¿Podría el temporizador ser recostackdo en el ejemplo anterior? Lo ejecuté por un tiempo y nunca recibí una excepción ni un mensaje que dijera ~Program() .

ACTUALIZACIÓN: descubrí a partir de esta pregunta ( gracias sethcran ) que los subprocesos son rastreados por el CLR, pero aún me gustaría obtener una respuesta sobre los temporizadores.

Esto es solo un problema con la clase System.Threading.Timer si de lo contrario no almacena una referencia en algún lugar. Tiene varias sobrecargas de constructor, las que toman el objeto de estado son importantes. El CLR presta atención a ese objeto de estado. Siempre que se haga referencia a él en alguna parte, el CLR mantiene el temporizador en su cola de temporizador y el objeto del temporizador no obtendrá basura recolectada. La mayoría de los progtwigdores no usarán ese objeto de estado, el artículo de MSDN ciertamente no explica su función.

System.Timers.Timer es un contenedor para la clase System.Threading.Timer, por lo que es más fácil de usar. En particular, usará ese objeto de estado y mantendrá una referencia siempre que el temporizador esté habilitado.

Tenga en cuenta que en su caso, la propiedad Enabled del temporizador es falsa cuando ingresa su controlador de eventos de Elapsed porque tiene AutoReset = false. Por lo tanto, el temporizador es elegible para la recostackción tan pronto ingrese en su controlador de eventos. Pero no se meta en problemas al hacer referencia al argumento del remitente , que se requiere para volver a establecer Habilitado en verdadero. Lo que hace que el jitter informe la referencia para que no tenga un problema.

Tenga cuidado con el controlador de eventos de Elapsed. Cualquier excepción arrojada dentro de ese método será tragada sin un diagnóstico. Lo que también significa que no volverá a establecer Habilitado en verdadero. Debe usar try / catch para hacer algo razonable. Si no va a finalizar su progtwig intencionalmente, como mínimo deberá informar a su progtwig principal que algo no funciona. Poner habilitado = verdadero en una cláusula finally puede evitar que se recolecte la basura del temporizador, pero a riesgo de que su progtwig genere excepciones una y otra vez.

Agregue este código a un progtwig y ejecútelo. Verás que el temporizador NO se recostack.

  private void DoStuff() { CreateTimer(); Console.WriteLine("Timer started"); int count = 0; for (int x = 0; x < 1000000; ++x) { string s = new string("just trying to exercise the garbage collector".Reverse().ToArray()); count += s.Length; } Console.WriteLine(count); Console.Write("Press Enter when done:"); Console.ReadLine(); } private void Ticktock(object s, System.Timers.ElapsedEventArgs e) { Console.WriteLine("Ticktock"); } private void CreateTimer() { System.Timers.Timer t = new System.Timers.Timer(); // Timer(Ticktock, null, 1000, 1000); t.Elapsed += Ticktock; t.Interval = 1000; t.AutoReset = true; t.Enabled = true; } 

Entonces, la respuesta a su pregunta parece ser que el temporizador no es elegible para la recostackción y no se recostackrá si no mantiene una referencia.

Es interesante observar que si ejecuta la misma prueba con System.Threading.Timer , encontrará que el temporizador se recostack.