Для System.Timers.Timer, в отдельном потоке, если SynchronizingObject не установлен.
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;
}
Вывод, который вы увидите, если DummyTimer сработает с интервалом в 5 секунд:
Main Thread Id: 9
12
12
12
12
12
...
Итак, как видно, OnDummyTimerFired выполняется в рабочем потоке.
Нет, дальнейшее осложнение - если вы уменьшите интервал до 10 мс,
Main Thread Id: 9
11
13
12
22
17
...
Это связано с тем, что если предварительное выполнение OnDummyTimerFired не было выполнено при запуске следующего тика, тогда .NET создаст новый поток для выполнения этой работы.
Все усложняется, "Класс System.Timers.Timer предоставляет простой способ решения этой дилеммы - он предоставляет открытое свойство SynchronizingObject. Установка этого свойства для экземпляра формы Windows (или элемента управления форма Windows) обеспечит выполнение кода в обработчике Elapsed в том же потоке, в котором был создан объект SynchronizingObject. "
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx#S2