我有一个主线程创建一个表单对象,该表单对象设置了一个定时器每分钟运行一次名为updateStatus()的函数。但是,updateStatus()也被主线程在几个地方调用。
然而,我不清楚这是否会导致任何同步问题。在C#中,System.Windows.Forms.Timer是否在与主线程不同的线程上运行?
不,计时器事件是在UI线程上触发的。
您不会有任何同步问题。这是WinForms应用程序中使用的正确版本的计时器控件;它是专门设计来执行您所要求的操作的。它在幕后使用标准的Windows计时器实现。
文档在备注部分确认了这一点:
定时器用于在用户定义的时间间隔内引发事件。此Windows计时器适用于单线程环境,其中使用UI线程执行处理。它要求用户代码有一个可用的UI消息泵,并始终从相同的线程操作,或将调用排队到另一个线程。
当您使用此计时器时,请使用Tick事件执行轮询操作或显示指定时间的启动屏幕。每当Enabled属性设置为true且Interval属性大于零时,Tick事件会根据Interval属性设置间隔地引发。
不。
Windows.Forms计时器的整个重点在于它在GUI线程上运行。
Windows (WinForms) 运行的是一种称为“消息泵”的东西(请参见Application.Run()
),这就使得计时器成为可能。
您所有的代码都作为事件处理程序的一部分运行,而计时器的滴答声永远不会“中断”任何其他事件处理程序。
Windows.Forms计时器将事件通过同步上下文返回到UI线程。
如果你想使用非UI线程,可以使用其他计时器,例如System.Timers.Timer或System.Threading.Timer。
我不想贬低其他回答者的声誉,他们说Windows.Forms.Timer
总是在GUI线程上运行,但我必须反驳一下。 :)
我的回答是 - 这取决于情况。 Windows.Forms.Timer
可能会在非GUI线程上运行!
Windows.Forms.Timer
会在包含计时器的Form
所在的线程上触发Timer.Tick
事件。
如果该窗体是在GUI线程上创建的,则Timer.Tick
在GUI线程上运行,但如果Form
是在例如某个线程池中的XXX线程上创建的(应避免这种情况),则Timer.Tick
将在此XXX线程上运行。
Task.Run(()=>
{
using (var formWithTimer = new SomeFormWithTimer()) //Form created on worker thread, Tick handled on it.
{
formWithTimer.ShowDialog();
}
});
Timer.Tick
可能在非 GUI 线程上运行的情况下?;) - RekshinoTimer.Tick
不一定必须在 GUI 线程上运行,即使这不是一个现实的情况。 - Rekshino
Paint
或Load
事件。你也不需要锁定这些处理程序。 - Cody Gray