Para System.Timers.Timer, em thread separado, se SynchronizingObject não estiver definido.
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;
}
Saída que você veria se DummyTimer disparasse em um intervalo de 5 segundos:
Main Thread Id: 9
12
12
12
12
12
...
Portanto, como visto, OnDummyTimerFired é executado no thread Workers.
Não, complicação adicional - Se você reduzir o intervalo para 10 ms,
Main Thread Id: 9
11
13
12
22
17
...
Isso ocorre porque se a execução anterior de OnDummyTimerFired não for feita quando o próximo tique for disparado, o .NET criará um novo encadeamento para fazer esse trabalho.
Para complicar ainda mais, "a classe System.Timers.Timer fornece uma maneira fácil de lidar com esse dilema - ela expõe uma propriedade pública SynchronizingObject. Definir essa propriedade para uma instância de um formulário do Windows (ou um controle em um formulário do Windows) garantirá que o código em seu manipulador de eventos Elapsed é executado no mesmo thread em que o SynchronizingObject foi instanciado. "
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx#S2