计时器在交叉线程中不起作用

我的表单中有2个全局System.Windows.Forms.Timer 。 两者都在表单的构造函数中初始化。 但尚未开始。 构造函数启动一个新线程 ,该线程启用并启动两个计时器。 显然它是所有交叉线程 ,但它不会抛出任何跨线程exception。 但它甚至不起作用。 它不会触发Timer.Tick方法。 这是代码:

第一种方法:

在表单构造函数中:

  KeepMeAliveTimer = new Timer(); //timer 1 KeepMeAliveTimer.Interval = 15000; KeepMeAliveTimer.Tick += KeepMeAlive; timer1 = new Timer(); //timer 2 timer1.Interval = 15000; timer1.Tick += timer1_Tick; //started a new thread 

在新的thead:

  //after performing some tasks, it enables the timers KeepMeAliveTimer.Enabled = true; //timer 1 KeepMeAliveTimer.Start(); timer1.Enabled = true; //timer 2 timer1.Start(); 

但它没有启动Timer的tick事件,甚至没有抛出任何exception。

第二种方法:

但是当我在同一个线程(主线程)中初始化并启用Timers ,它们完美地工作:

  KeepMeAliveTimer = new Timer(); //timer 1 KeepMeAliveTimer.Interval = 15000; KeepMeAliveTimer.Tick += KeepMeAlive; KeepMeAliveTimer.Enabled = true; KeepMeAliveTimer.Start(); timer1 = new Timer(); //timer 2 timer1.Interval = 15000; timer1.Tick += timer1_Tick; timer1.Enabled = true; timer1.Start(); 

现在的问题是; 如果没有任何exception,为什么第一种方法不起作用?

Timer类是线程安全的,但不是你想象的那样。 在工作线程上调用Start()方法实际上启动了计时器。 该类经历了创建隐藏窗口的工作,因此它可以调用SetTimer winapi函数并在完成后接收WM_TIMER消息。

但是,如果没有人正在侦听该消息,则无法引发Tick事件。 你不会,你肯定没有在该线程上调用Application.Run()。 因此,您不应该在工作线程上启动计时器。 如有必要,请使用Control.BeginInvoke在UI线程上启动它。

或者使用System.Threading.Timer或System.Timers.Timer,它们不依赖于消息循环。 你必须正确地互锁,他们的Elapsed事件或回调在另一个线程上运行。 哪种解决方案往往会产生另一个问题。