我有一个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();
上(但有时只有,我看不到在发生这种情况的地方重复的模式,它只是动态的)
有人遇到过类似的问题并解决了吗?
实际上不支持阻塞UI。虽然UI线程上"支持"有等待例程(这意味着它们识别出有一个消息泵,并在等待时泵送消息),但通常这样做不是一个好主意。
首先,您正在阻塞UI。是的,某些消息泵送在某些情况下可能会发生,但您真的希望UI线程处理消息和等待吗?如果你真的不小心,就会造成灾难。
让我们来看一个简单的场景。假设您在编写Timer
回调时已经进行了尽职调查(因为您选择了System.Threading.Timer
,而不是"System.Windows.Forms.Timer",它实际上在UI线程上运行Tick
事件处理程序),并选择使用Control.Invoke
将数据封送回UI线程(或使用WPF的Dispatcher.Invoke
,您还没有指定所说的Windows应用程序的类型)。从概念上讲,您得到了一个Stop
方法,该方法处理Timer
并停止回调。Timer
的Dispose
方法被记录为,可以在调用Dispose
之后调用回调,因此这是一个竞争条件,但也可能在调用Dispose
的同时调用回调。这两种情况都意味着,在Dispose
和WaitOne
之间(或者实际上只是在WaitOne
之前的),Timer
回调可能会对Invoke
进行调用。CCD_ 19正在阻塞并等待UI线程处理该消息。但是,如果您的Stop
方法被UI上的某些东西(即消息)调用,则意味着消息泵在WaitOne
上被阻止死锁。
可以,可能,通过用BeginInvoke切换出Invoke来解决此问题。但是,您最终仍然会阻塞UI线程——在大多数情况下,它无法处理有用的消息。
你的问题并没有详细说明你试图做什么,所以基本上不可能准确地告诉你,也不可能确切地告诉你该怎么解决你的问题。简短的回答是:重新设计,这样你就不必等待了。如果你仍然坚持这一点,我建议问一个不同的问题,概述你想完成什么,你已经尝试了什么,以及如何做才能做得更好。