¿Un System.Timers.Timer transcurre en un hilo diferente al hilo que lo creó?
Digamos que tengo una clase con un temporizador que se activa cada 5 segundos. Cuando se dispara el temporizador, en el método transcurrido, se modifica algún objeto. Digamos que se necesita mucho tiempo para modificar este objeto, como 10 segundos. ¿Es posible que me encuentre con colisiones de subprocesos en este escenario?
c#
multithreading
timer
usuario113164
fuente
fuente
Respuestas:
Para System.Timers.Timer :
Vea la respuesta de Brian Gideon a continuación
Para System.Threading.Timer :
La documentación de MSDN sobre temporizadores indica:
Entonces, de hecho, el temporizador transcurre en un hilo diferente.
fuente
Depende. El
System.Timers.Timer
tiene dos modos de funcionamiento.Si
SynchronizingObject
se establece en unaISynchronizeInvoke
instancia, elElapsed
evento se ejecutará en el hilo que aloja el objeto de sincronización. Por lo general, estosISynchronizeInvoke
casos no son más que casos antiguosControl
y con losForm
que todos estamos familiarizados. Entonces, en ese caso, elElapsed
evento se invoca en el subproceso de la interfaz de usuario y se comporta de manera similar aSystem.Windows.Forms.Timer
. De lo contrario, realmente depende de laISynchronizeInvoke
instancia específica que se utilizó.Si
SynchronizingObject
es nulo, elElapsed
evento se invoca en unThreadPool
hilo y se comporta de forma similar aSystem.Threading.Timer
. De hecho, en realidad utiliza unSystem.Threading.Timer
detrás de escena y realiza la operación de clasificación después de recibir la devolución de llamada del temporizador si es necesario.fuente
System.Threading.Timer
oSystem.Timers.Timer
?System.Timers.Timer
tiene dos modos de funcionamiento. Puede ejecutarse en un subproceso de grupo de subprocesos asignado aleatoriamente O puede ejecutarse en cualquier subproceso que aloje laISynchronizeInvoke
instancia. No sé cómo dejar eso más claro.System.Threading.Timer
tiene poco (si es que tiene algo) que ver con la pregunta original.lock
para eso?Cada evento transcurrido se activará en el mismo hilo a menos que se esté ejecutando un evento anterior.
Entonces maneja la colisión por ti
intenta poner esto en una consola
obtendrás algo como esto
donde 10 es el hilo de llamada y 6 y 12 se disparan desde el evento bg transcurrido. Si quita Thread.Sleep (2000); obtendrás algo como esto
Dado que no hay colisiones.
Pero esto todavía te deja con un problema. Si dispara el evento cada 5 segundos y se tarda 10 segundos en editar, necesita un poco de bloqueo para omitir algunas ediciones.
fuente
timer.Stop()
al comienzo del método de evento Elapsed y luegotimer.Start()
al final del método de evento Elapsed evitará que el evento Elapsed choque.Para System.Timers.Timer, en un subproceso separado, si SynchronizingObject no está configurado.
Salida que vería si DummyTimer se disparara en un intervalo de 5 segundos:
Entonces, como se ve, OnDummyTimerFired se ejecuta en el hilo de Workers.
No, más complicaciones: si reduce el intervalo para decir 10 ms,
Esto se debe a que si la ejecución previa de OnDummyTimerFired no se realiza cuando se activa el siguiente tick, entonces .NET crearía un nuevo hilo para hacer este trabajo.
Para complicar aún más las cosas, "La clase System.Timers.Timer proporciona una manera fácil de lidiar con este dilema: expone una propiedad pública SynchronizingObject. Establecer esta propiedad en una instancia de un formulario de Windows (o un control en un formulario de Windows) asegurará que el código de su controlador de eventos Elapsed se ejecuta en el mismo hilo en el que se creó una instancia de SynchronizingObject ".
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx#S2
fuente
Si el evento transcurrido tarda más que el intervalo, se creará otro hilo para generar el evento transcurrido. Pero hay una solución para esto
fuente