WindowsCE 5.0,.NET Compact framework 3.5
我需要定期更新UI,所以我决定使用Threading.Timer。我的代码如下所示,除了在Timer的回调过程中出现Presenter.Stop()外,它的效果很好。
调试输出表明它从UpdateViewSafe退出并且Stop将始终在Monitor.Enter(sync)处等待。我的错在哪里?我尝试使用Thread而不是Timer,但它也在Thread的回调中死锁,所以我猜在锁定同步对象和Control.Invoke之间的问题。
源代码:
class Presenter
{
private MyForm view;
private Timer timer;
private object sync;
public Presenter(MyForm form)
{
view = form;
sync = new object();
}
public void Start()
{
timer = new Timer(UpdateViewSafe, null, 0, 2000);
}
public void Stop()
{
System.Diagnostics.Debug.WriteLine("+++ Stop 1");
Monitor.Enter(sync);
timer.Change(Timeout.Infinite, Timeout.Infinite);
timer.Dispose();
Monitor.Exit(sync);
System.Diagnostics.Debug.WriteLine("+++ Stop 2");
}
private void UpdateViewSafe(object state)
{
System.Diagnostics.Debug.WriteLine("+++ UpdateViewSafe 1");
Monitor.Enter(sync);
System.Diagnostics.Debug.WriteLine("+++ UpdateViewSafe 2");
Thread.Sleep(1000);
System.Diagnostics.Debug.WriteLine("+++ UpdateViewSafe 3");
view.InvokeIfNeeded(() => view.MyText = "text");
Monitor.Exit(sync);
System.Diagnostics.Debug.WriteLine("+++ UpdateViewSafe 4");
}
}
public static void InvokeIfNeeded(this Control control, Action doIt)
{
if (control == null) return;
if (control.InvokeRequired)
control.Invoke(doIt);
else
doIt();
}
调试输出:
+++ UpdateViewSafe 1
+++ UpdateViewSafe 2
+++ Stop 1
+++ UpdateViewSafe 3
我从未见过
+++ Stop 2
答案 0 :(得分:1)
我需要定期更新UI,所以我决定使用Threading.Timer。
当您使用Winforms时,我建议您改用System.Windows.Forms.Timer
。它使用UI消息泵,因此代码在与UI相同的线程中执行,这意味着:
Invoke
来更新您的UI控件你不会有很好的精确度(约50毫秒),但在大多数情况下,它应该足以进行UI更新。
附注:使用lock(lockObject){ ... }
代替Monitor
(几乎相同但更容易使用,因为关键部分范围已实现)
答案 1 :(得分:0)
由于我们没有看到如何调用Start
和Stop
,因此很难确切知道如何获得输出。
Stop
可能会在UpdateViewSafe
进入监视器之前调用并安排UpdateViewSafe
,但它没有得到时间片。这允许Sleep
执行到Stop
,此时上下文切换到运行Monitor.Enter
的线程,该线程执行到它等待的UpdateViewSafe
。此时+++ UpdateViewSafe 1
+++ UpdateViewSafe 2
+++ Stop 1
+++ UpdateViewSafe 3
+++ UpdateViewSafe 4
+++ Stop 2
再次开始运行。
我也没有看到你输出的其余部分,但我猜你总能看到这个
{{1}}
尽管最后两行很可能会被交换,这取决于你最终如何调度量程。它绝对可以以任何一种方式运行,所以不要依赖于其中一种。
如果你想控制“Stop 1”输出,那么它需要在关键部分内 - 这就是关键部分的工作原理。