使用Visual Studio 2015和Visual C#Windows应用程序。
我需要一个计时器来清空主线程中的队列,因为某些UI组件已被修改。我编码为:
public Form1() { InitializeComponent(); Q = new ConcurrentQueue(); 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); }
但是Elapsed事件在工作线程中执行...?
如果在设计时在主窗体上放置一个计时器,则生成的原型会略有不同:
private void timer1_Tick(object sender, EventArgs e) { amsg msg; while (Q.TryDequeue(out msg)) handleRx(msg); }
但这确实在主线程上下文中执行。
问题扩展到以这种方式创建计时器的任何线程。我以为在线程中创建的计时器会在同一线程上下文中执行经过的事件。我想念什么吗?
快速编辑:我看到这些是System.Timers.Timer和Windows.Forms.Timer不同的计时器。那么-如何可靠地创建将在创建计时器的线程中执行的计时器?
是的,您只需要处理两个单独的Timer
类。 System.Windows.Forms.Timer
触发其Tick
主线程上的事件,并System.Timers.Timer
触发其Elapsed
在后台线程事件。好处System.Windows.Forms.Timer
是它隐藏了线程。的优点System.Timers.Timer
是它不需要消息泵即可工作。
您问:“如何可靠地创建将在创建计时器的线程中执行的计时器?” 好吧,当您具有Windows Forms GUI并在UI线程上启动Timer时,这很容易:只需使用System.Windows.Forms.Timer
。如果您没有利用消息泵的方法,则必须使用a System.Timers.Timer
并基本上是在计时器触发其Elapsed
事件时在主线程上运行某些内容的唯一方法是在主线程中重新创建类似消息循环的内容, -坐好,可能正在等待Monitor.Pulse
计时器线程的通知或其他某种通知。但这意味着您的主线程在此期间不会做任何有用的事情...