计时器不跨线程工作 [英] Timer is not working in cross threads

查看:122
本文介绍了计时器不跨线程工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆