c# - tag - System.Windows.Forms.Timer no se activa
timer c# windows form (3)
El temporizador de winforms es un control y se debe usar colocándolo en un formulario. Nunca lo agregas a una colección de control, así que no esperaría que funcione correctamente. La documentación dice lo siguiente
Implementa un temporizador que plantea un evento a intervalos definidos por el usuario. Este temporizador está optimizado para su uso en aplicaciones de Windows Forms y debe utilizarse en una ventana.
Por lo tanto, sugiero que use una instancia de la clase System.Timers.Timer . Esta clase se puede usar en cualquier lugar.
Tenga en cuenta que el evento Tick que usa arriba, es llamado por otro nombre en la clase System.Timer.Timer, es decir, el evento Elapsed .
Quiero utilizar System.Windows.Forms.Timer
para asegurarme de que un evento se desencadene en el subproceso de IU de un complemento de Excel que estoy creando. Construyo el temporizador de la siguiente manera:
private System.Windows.Forms.Timer _timer;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Debug.WriteLine("ThisAddIn_Startup:" + Thread.CurrentThread.ManagedThreadId);
_timer = new System.Windows.Forms.Timer();
_timer.Tick += new EventHandler(TimerEventHandler);
_timer.Interval = 500;
}
El temporizador es disparado por un evento COM de una biblioteca que estoy usando:
private void OnEvent()
{
_timer.Start();
}
Entonces espero que el _timer
llame al siguiente método cuando marca:
public void TimerEventHandler(object sender, EventArgs args)
{
_timer.Stop();
Debug.WriteLine("Tick: " + Thread.CurrentThread.ManagedThreadId);
}
Según tengo entendido, cuando creo el temporizador en el subproceso Addin, aunque se haya iniciado desde otro subproceso (evento COM en este caso), debe iniciarse en el subproceso en el que se creó, es decir, el subproceso addin. Sin embargo, esto no sucede.
He implementado este mecanismo exacto en un RTDServer
que escribí en el pasado ( como lo describe Kenny Kerr ) y funciona como se esperaba, pero el _timer
en este escenario nunca funciona.
También he leído otros artículos de SO que señalan el mismo comportamiento y no puedo entender qué es diferente acerca de mi configuración de complemento.
EDITAR: El método OnEvent () se dispara.
Todavía no entiendo por qué Forms.Timer no funciona como se esperaba, pero el siguiente excelente artículo explica en detalle cómo ordenar el trabajo en el hilo de UI: http://www.codeproject.com/Articles/31971/ Comprensión- SynchronizationContext-Part-I
Inicialmente quise publicar esto como comentario, pero resultó ser demasiado largo.
En primer lugar, la estructura de tus hilos me confunde un poco, tal como la describes. Coloque Debug.WriteLine("OnEvent:" + Thread.CurrentThread.ManagedThreadId)
dentro de OnEvent
y déjenos saber todos los identificadores de subprocesos que ve desde su salida de depuración.
Dicho eso, las reglas son:
Debería crear el objeto
Timer
WinForms en un hilo STA , y el hilo debería configurarse como STA antes de que comience.Este hilo puede ser o no el hilo principal de la interfaz de usuario (donde se creó el formulario principal), pero aún así debe ejecutar un ciclo de mensajes (con Application.Run ) para que se activen los eventos del temporizador. Hay otras formas de transmitir mensajes ( ejemplo ), pero generalmente no se controla desde el código .NET.
Debe manejar los eventos originados por WinForms ''
Timer
en el mismo hilo que se creó. A continuación, puede ''reenviar'' estos eventos a otro contexto de subproceso si lo desea (utilizando SynchronizationContextSend
oPost
) pero no puedo pensar en ninguna razón para dicha complejidad.
La respuesta de @Maarten en realidad sugiere la forma correcta de hacerlo, en mi opinión.