Para System.Timers.Timer, en un subproceso separado, 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 se 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 de Workers.
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 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