2016-01-06 58 views
0

使用Visual Studio 2015,Visual C#windows应用程序。定时器运行在与创建它不同的线程中

我需要一个计时器,清空主线程中的队列,因为一些UI组件被修改。我这个编码:

public Form1() 
    { 
     InitializeComponent(); 
     Q = new ConcurrentQueue<amsg>(); 
     timer = new System.Timers.Timer(100); 
     timer.Elapsed += timer_Elapsed; 
     timer.Enabled = true; 
    } 

    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     clsUdpMsg msg; 
     while (Q.TryDequeue(out msg)) handleRx(msg); 
    } 

,但经过的事件在辅助线程执行...?

如果我把一个计时器在设计时在主窗体上生成的原型是稍有不同:

private void timer1_Tick(object sender, EventArgs e) 
    { 
     amsg msg; 
     while (Q.TryDequeue(out msg)) handleRx(msg); 
    } 

但一个人在主线程上下文中执行。

这个问题延伸到任何创建一个计时器的线程;我认为在线程中创建的计时器在同一个线程上下文中执行已用过的事件。我错过了什么吗?

快速编辑:我看到这些是不同的定时器,System.Timers.Timer和Windows.Forms.Timer。那么 - 我如何可靠地创建将在创建它们的线程中执行的定时器?

+1

他们是2个不同的计时器。第一个来自'System.Timers','Windows.Forms.Timer'是第二个 – Plutonix

+0

.net中有4个定时器,还有'System.Threading.Timer'和'System.Windows.Threading。DispatcherTimer'也 –

回答

4

是的,你只是处理两个单独的Timer类。 System.Windows.Forms.Timer在主线程上触发Tick事件,System.Timers.Timer在后台线程上触发Elapsed事件。 System.Windows.Forms.Timer的优点是它隐藏了线程; System.Timers.Timer的优点是它不需要消息泵工作。

你问,“我如何可靠地创建将在创建它们的线程中执行的计时器?”好吧,当你有一个Windows窗体GUI并且在UI线程上启动Timer时,这很容易:只需使用System.Windows.Forms.Timer即可。如果你没有消息泵来利用,你必须使用System.Timers.Timer,并且当计时器触发Elapsed事件时,在主线程上运行某些东西的唯一方法是重新创建类似主消息循环的东西线程 - 让它坐下,也许等待Monitor.Pulse或其他类型的计时器线程通知。但是这意味着你的主线程不会在这段时间内完成任何有用的工作......

+0

所以它看起来最好的做法是假设所有计时器事件不是线程安全的...在这种情况下,我可以使用Windows计时器。感谢闪电般的快速解答! – user3235770

+0

我不太喜欢你在这里。 “所有计时器事件不是线程安全的”是什么意思? – adv12

+1

事件是线程安全的,问题是您的处理程序是否是。如果你不必担心UI线程,那么如果可能的话,最好的办法就是拥有一个线程安全处理程序,这样你就不必关心它运行的线程了。 –

0

这不是直接回答你的问题,而是一个避免定时器线程问题的建议。

你总是可以使用微软的Reactive Framework(NuGet“Rx-WinForms”)。

您的代码应该是这样的:

var subject = new Subject<clsUdpMsg>(); 

var subscription = 
    subject 
     .ObserveOn(this) 
     .Subscribe(msg => handleRx(msg)); 

subject替换您Q。每当你想添加一条消息,你只需拨打subject.OnNext(msg)

即使在后台线程上对subject.OnNext(msg)进行调用,.ObserveOn(this)也会将回调收回回UI。

如果您想停止订阅,请致电subscription.Dispose()

相关问题