我有Timer
做了几件事
private System.Threading.Timer _xTimer = new System.Threading.Timer(new TimerCallback(XTimerHandler), null, 0, _xTimerPollingInterval);
private void XTimerHandler(object param)
{
//some code.
}
我有一个停止计时器的功能:
private void Stop()
{
//some code.
if (_xTimer != null)
{
ManualResetEvent timerDisposeHandler = new ManualResetEvent(false);
_xTimer.Dispose(timerDisposeHandler);
_dataProcessingTimer = null;
//wait for dispose end.
timerDisposeHandler.WaitOne();
}
}
发生了一些非常奇怪的事情!
有时候所有的GUI都挂在timerDisposeHandler.WaitOne();
上(但只有有时候,我看不到一个模式会在它发生的地方重复,它只是动态的)
有没有人遇到类似问题并解决了?
答案 0 :(得分:1)
实际上不支持阻止UI。虽然是等待例程,但是#34;支持"在UI线程上(这意味着他们认识到有消息泵和消息,而你等待),一般来说这不是一个好主意。
首先,您要阻止用户界面。是的,在某些情况下可能会出现某些消息,但您真的希望UI线程处理消息和等待吗?如果您不是真的,真的小心,请为灾难准备。
让我们来看一个简单的场景。让我们说您在撰写Timer
回调时已经完成了尽职调查(因为您选择了System.Threading.Timer
而不是#34; System.Windows.Forms。 Timer"实际上在UI线程上运行Tick
事件处理程序)并选择使用Control.Invoke
(或Dispatcher.Invoke
使用WPF将数据封送回UI线程,你没有&# 39; t指定了您正在谈论的Windows应用程序类型。从概念上讲,您已经获得Stop
方法来处理Timer
并停止回调。 Dispose
的{{1}}方法被记录为可以在调用Timer
之后调用回调,因此可以调用竞争条件,但也可能会调用回调函数你打电话给Dispose
的时间。这两种情况都表示在Dispose
和Dispose
之间(或者只是之前 WaitOne
),WaitOne
回调可能会调用Timer
1}}。 Invoke
正在阻塞并等待UI线程处理该消息。但是,如果您的Invoke
方法被UI上的某些内容(即消息)调用,则意味着消息泵在Stop
上被阻止。 死锁
可能可以通过使用 BeginInvoke 切换 Invoke 来解决此问题。但是,你仍然最终阻止了UI线程 - 在大多数情况下,保持它不会处理有用的消息。
您的问题没有详细说明您尝试做什么,所以基本上不可能告诉您完全,或者任何确定性,如何解决您的问题。简短的回答:重新设计,所以你不必等待。如果您仍然坚持这一点,我建议您提出一个不同的问题,概述您想要完成的内容,您尝试过的内容以及如何执行此操作更好。