c# - tiempo - vb threading timer
¿Los cronómetros C#transcurren en un hilo separado? (5)
Cada evento transcurrido se activará en el mismo subproceso a menos que todavía se esté ejecutando un Elapsed previo.
Por lo tanto, maneja la colisión para usted
intenta poner esto en una consola
static void Main(string[] args)
{
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
var timer = new Timer(1000);
timer.Elapsed += timer_Elapsed;
timer.Start();
Console.ReadLine();
}
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
Thread.Sleep(2000);
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
obtendrás algo como esto
10
6
12
6
12
donde 10 es el hilo que llama y 6 y 12 están disparando desde el evento transcurrido bg. Si elimina el Thread.Sleep (2000); obtendrás algo como esto
10
6
6
6
6
Como no hay colisiones
Pero esto todavía te deja con un problema. si está activando el evento cada 5 segundos y tarda 10 segundos en editarlo, necesita un bloqueo para omitir algunas ediciones.
¿Transmite un System.Timers.Timer un hilo separado del hilo que lo creó?
Digamos que tengo una clase con un temporizador que se dispara cada 5 segundos. Cuando el temporizador se dispara, en el método transcurrido, se modifica algún objeto. Digamos que lleva mucho tiempo modificar este objeto, como 10 segundos. ¿Es posible que me encuentre con colisiones de hilos en este escenario?
Para System.Timers.Timer, en una secuencia separada, si SynchronizingObject no está configurado.
static System.Timers.Timer DummyTimer = null;
static void Main(string[] args)
{
try
{
Console.WriteLine("Main Thread Id: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
DummyTimer = new System.Timers.Timer(1000 * 5); // 5 sec interval
DummyTimer.Enabled = true;
DummyTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnDummyTimerFired);
DummyTimer.AutoReset = true;
DummyTimer.Start();
Console.WriteLine("Hit any key to exit");
Console.ReadLine();
}
catch (Exception Ex)
{
Console.WriteLine(Ex.Message);
}
return;
}
static void OnDummyTimerFired(object Sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
return;
}
Salida que vería si DummyTimer disparara en un intervalo de 5 segundos:
Main Thread Id: 9
12
12
12
12
12
...
Entonces, como se ve, OnDummyTimerFired se ejecuta en el hilo Trabajadores.
No, más complicaciones: si reduce el intervalo para decir 10 ms,
Main Thread Id: 9
11
13
12
22
17
...
Esto se debe a que si la ejecución previa de OnDummyTimerFired no se realiza cuando se activa el siguiente tic, entonces .NET creará 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 Public SynchronizingObject. Establecer esta propiedad en una instancia de Windows Form (o un control en Windows Form) asegurará que el código en su controlador de eventos de Elapsed se ejecuta en el mismo hilo en el que SynchronizingObject fue instanciado ".
Si el evento transcurrido toma más tiempo que el intervalo, creará otro hilo para elevar el evento transcurrido. Pero hay una solución para esto
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
timer.Stop();
Thread.Sleep(2000);
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
finally
{
timer.Start();
}
}
Para System.Timers.Timer :
Ver la respuesta de Brian Gideon a continuación
Para System.Threading.Timer :
MSDN Documentation on Timers states:
La clase System.Threading.Timer realiza devoluciones de llamada en un subproceso de ThreadPool y no utiliza el modelo de evento en absoluto.
De hecho, el temporizador transcurre en un hilo diferente.
Depende. El System.Timers.Timer
tiene dos modos de operación.
Si SynchronizingObject
se establece en una instancia de ISynchronizeInvoke
, el evento de ISynchronizeInvoke
se ejecutará en el hilo que aloja el objeto de sincronización. Por lo general, estas instancias de ISynchronizeInvoke
no son más que simples instancias antiguas de Control
y Form
que todos estamos familiarizados. Entonces, en ese caso, el evento Elapsed
se invoca en el subproceso de la interfaz de usuario y se comporta de manera similar al System.Windows.Forms.Timer
. De lo contrario, realmente depende de la instancia específica de ISynchronizeInvoke
que se usó.
Si SynchronizingObject
es nulo, el evento Elapsed
se invoca en un subproceso de ThreadPool
y se comporta de forma similar al System.Threading.Timer
. De hecho, en realidad usa un System.Threading.Timer
detrás de las escenas y realiza la operación de cálculo de referencias después de que recibe la devolución de llamada del temporizador si es necesario.