System.Windows.Forms.Timer没有触发
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了System.Windows.Forms.Timer没有触发相关的知识,希望对你有一定的参考价值。
我想使用System.Windows.Forms.Timer
来确保在我正在创建的excel插件的UI线程上触发事件。我按如下方式构建计时器:
private System.Windows.Forms.Timer _timer;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Debug.WriteLine("ThisAddIn_Startup:" + Thread.CurrentThread.ManagedThreadId);
_timer = new System.Windows.Forms.Timer();
_timer.Tick += new EventHandler(TimerEventHandler);
_timer.Interval = 500;
}
计时器是由我正在使用的库中的COM事件触发的:
private void OnEvent()
{
_timer.Start();
}
然后我希望_timer
在勾选时调用以下方法:
public void TimerEventHandler(object sender, EventArgs args)
{
_timer.Stop();
Debug.WriteLine("Tick: " + Thread.CurrentThread.ManagedThreadId);
}
据我所知,当我在Addin线程中创建计时器时,即使它是从另一个线程(在这种情况下是COM事件)启动的,它应该触发它所创建的线程,即插件线程。但是,这不会发生。
我已经在我过去写的RTDServer
(as outlined by Kenny Kerr)中实现了这个确切的机制,它按预期工作,但在这种情况下_timer
永远不会滴答。
我也读过other SO articles指向相同的行为,无法弄清楚我的插件设置有什么不同?
编辑:触发OnEvent()方法。
我最初的意思是发布这个评论,但它变得太长了。
首先,你的线程结构对我来说有点混乱,就像你描述的那样。将Debug.WriteLine("OnEvent:" + Thread.CurrentThread.ManagedThreadId)
放在OnEvent
中,让我们知道您从调试输出中看到的所有线程ID。
也就是说,规则是:
- 您应该在
Timer
上创建WinForms的STA thread对象,并且线程应该在它开始之前配置为STA。 - 此线程可能是也可能不是主UI线程(创建主窗体的位置),但仍应执行消息循环(使用Application.Run)以触发计时器事件。还有其他方法可以提取消息,但通常不会从.NET代码中控制它们。
- 您应该在WinForms的
Timer
创建的同一个线程上处理源代码。然后,如果您愿意,可以将这些事件“转发”到另一个线程上下文(使用SynchronizationContextSend
或Post
),但我无法想到这种复杂性的任何原因。
在我看来,@ Maarten的答案实际上表明了正确的做法。
winforms计时器是一个控件,必须通过将其放在表单上来使用。你永远不会把它添加到控件集合中,所以我不希望它能正常工作。 The documentation说以下内容
实现以用户定义的间隔引发事件的计时器。此计时器已针对Windows窗体应用程序进行了优化,必须在窗口中使用。
因此,我建议你使用System.Timers.Timer class的一个实例。这个类可以在任何地方使用。
请注意,您在上面使用的Tick-event由System.Timer.Timer类中的另一个名称调用,即Elapsed-event。
我还不明白为什么Forms.Timer没有按预期运行,但下面的优秀文章详细解释了如何将工作编组到UI线程:http://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I
以上是关于System.Windows.Forms.Timer没有触发的主要内容,如果未能解决你的问题,请参考以下文章