private static readonly TimeSpan timeout = TimeSpan.FromSeconds(10);
private static readonly object Synchronizer = new { };
public static void idle()
{
//make sure, it is only called from the Thread that updates.
AssertThread.Name("MyUpdateThreadName");
lock (Synchronizer) {
Monitor.Wait(Synchronizer, timeout);
}
}
public static void nudge()
{
//anyone can call this
lock (Synchronizer) {
Monitor.PulseAll(Synchronizer);
}
}
我不确定这两个答案是否真的是一个好主意。如果GUI更新(上帝保佑,但这是可能的,想象一下后台的Windows更新:-)花费超过1秒的时间会发生什么。这不会导致从创建线程的消息泵堵塞吗? 我在这里找到了答案:What if a timer can not finish all its works before the new cycle time arrives? 如果我们使用了正确的Timer类,一切都很好。吉姆·米歇尔:如果您使用的是System.Windows.Forms.Timer,则在前一个刻度完成处理之前,不会出现新的刻度。 我还在tick事件开始时停止计时器,然后再次启动它,但这只是因为我不需要连续两次更新。 通常我会使用Monitor Wait/Pulse,但在这种情况下,它非常舒适,计时器事件在gui线程中执行,所以没有必要做任何事情。 因为我也需要手动更新(即。不是从tick开始的),我的代码看起来像这样: 在InitializeComponent()之后
//if you use the wrong one here, you will get in great trouble :-)
guiUpdateTimer = new System.Windows.Forms.Timer { Interval = 1000 };
guiUpdateTimer.Tick += (sender, args) => updateGUI();
guiUpdateTimer.Start();
和
private void updateGUI()
{
guiUpdateTimer.Stop();
unsafe_updateGUI(); //inhere we actually access the gui
guiUpdateTimer.Start();
}
4条答案
按热度按时间57hvy0tb1#
使用Timer控件,它的UI线程被调用,并且是一个可通过窗体设计器使用的控件。
093gszye2#
您可以使用
System.Windows.Forms.Timer
控件刷新表单控件。试试这个:
m4pnthwp3#
这是我通常处理它的方式。
场景:一些线程应该每n秒更新一次,但我们希望能够在时间耗尽之前触发更新,而不会有阻塞任何东西的风险。
在这里,idle()将从执行更新的Thread调用,而nudge()可以从任何地方调用,以便在超时到期之前开始更新。
由于等待和脉冲之间的复杂相互作用-考虑到同步器的锁定状态,它的工作非常可靠,即使在很多轻推非常快的时候。这也有一个很好的副作用,即永远不会死(B)锁定更新线程。
当然,如果更新涉及GUI的东西,你将不得不采取整个PickeRequired之旅。这意味着在更新线程的while循环中,
sendinfo可能是某种Action或Delegate。而且你永远不会直接从GUI线程调用idle()!
到目前为止,我能找到的唯一不那么明显的行为是:如果你有很多nudges非常快,线程实际上是更新一个GUI,有一个巨大的差异之间的nudges()和Beginnudges()。根据你想要的,Brackke实际上给了GUI时间来对交互做出React,BeginBrackke可以快速地淹没消息泵,使GUI无法响应(在我的情况下,这是(奇怪的是)想要的行为:-))。
y1aodyip4#
我不确定这两个答案是否真的是一个好主意。如果GUI更新(上帝保佑,但这是可能的,想象一下后台的Windows更新:-)花费超过1秒的时间会发生什么。这不会导致从创建线程的消息泵堵塞吗?
我在这里找到了答案:What if a timer can not finish all its works before the new cycle time arrives?
如果我们使用了正确的Timer类,一切都很好。吉姆·米歇尔:如果您使用的是System.Windows.Forms.Timer,则在前一个刻度完成处理之前,不会出现新的刻度。
我还在tick事件开始时停止计时器,然后再次启动它,但这只是因为我不需要连续两次更新。
通常我会使用Monitor Wait/Pulse,但在这种情况下,它非常舒适,计时器事件在gui线程中执行,所以没有必要做任何事情。
因为我也需要手动更新(即。不是从tick开始的),我的代码看起来像这样:
在InitializeComponent()之后
和
如果将unsafe_updateGUI()调用 Package 在适当的sockeRequired检查中,则甚至可以从GUI线程外部调用它。
哦,是的,对于OP场景,这可能不是最好的方式去.