计时器不跨线程工作 [英] Timer is not working in cross threads
问题描述
我有2个全球 System.Windows.Forms.Timer
在我的格式即可。无论在形式的构造函数初始化。但尚未启动。构造函数启动新线程并线程允许并启动这两个定时器。显然,这是一切的跨线程,但它不抛出任何跨线程异常。但它甚至不工作。它不火的 Timer.Tick
方法。下面是代码:
I have 2 global System.Windows.Forms.Timer
in my form. Both are initialized in form's constructor. But not started yet. Constructor starts a new thread and that thread enables and starts both of the timers. Obviously it is all cross threading, but it doesn't throw any cross-thread exception. But it doesn't even work. It does not fire the Timer.Tick
method. Here is the code:
第1种方法:
在表单构造:
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();
但它不发射了计时器的Tick事件,甚至不扔任何异常。
But it is not firing up Timer's tick events and not even throwing any exception.
第2种方法:
但是,当我初始化并启用了定时器
在同一个线程(主线程),它们是完全工作:
But when I initialized and enabled the Timers
in the same thread (Main Thread) they are working perfectly:
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();
现在的问题是;为什么第一种方法是行不通的,如果竟然没有任何异常?
Now the question is; Why the first method is not working if there is not even any exception?
推荐答案
Timer类是线程安全的,但不你期望的方式。在调用工作线程的start()方法并真正开始计时。类经过创建隐藏的窗口,因此它可以调用SetTimer的WINAPI功能并且当完成接收所述WM_TIMER消息的努力。
The Timer class is thread-safe but not in the way you expect it. Calling the Start() method on worker thread does actually start the timer. The class goes through the effort of creating a hidden window so it can call the SetTimer winapi function and receive the WM_TIMER message when it is done.
但Tick事件不能提高。你不会,你肯定没有在该线程调用Application.Run()。因此,应在开始工作线程的计时器。必要时使用Control.BeginInvoke得到它开始在UI线程上。
But the Tick event cannot be raised if nobody is listening for that message. You won't be, surely you didn't call Application.Run() on that thread. You should therefore not start a timer on a worker thread. Use Control.BeginInvoke if necessary to get it started on the UI thread.
或者使用System.Threading.Timer或者System.Timers.Timer,他们不依赖于消息循环。你必须正确地互锁,他们已用事件或回调运行还的其他的线程。这是什么样的解决方案,往往会造成另一个问题。
Or use a System.Threading.Timer or System.Timers.Timer, they don't depend on a message loop. You do have to interlock properly, their Elapsed event or callback run on yet another thread. Which is the kind of solution that tends to create another problem.
这篇关于计时器不跨线程工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!