1

我有一个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();(但只是有时,我看不到在它发生的地方重复出现的模式,它只是动态地)

有没有人遇到过类似的问题并解决了?

4

1 回答 1

2

实际上不支持阻止 UI。虽然在 UI 线程上有“支持”等待例程(这意味着它们识别出有一个消息泵并您等待时泵送消息),但一般来说这样做并不是一个好主意。

首先,您正在阻止 UI。是的,在某些情况下可能会发生一些消息泵送,但是您真的希望 UI 线程处理消息等待吗?如果你不是真的非常小心,灾难的秘诀。

让我们看一个简单的场景。假设您在编写Timer回调时已经完成了尽职调查(因为您选择System.Threading.Timer而不是“System.Windows.Forms.Timer”,它实际上Tick在 UI 线程上运行事件处理程序)并选择将数据编组回使用Control.Invoke(或Dispatcher.Invoke使用 WPF,您尚未指定您正在谈论的 Windows 应用程序类型)的 UI 线程。从概念上讲,您有一个Stop处理Timer和停止回调的方法。记录的Dispose方法Timer是说可以在调用回调之后Dispose调用回调,因此是一种竞争条件,但也可能在您调用的同时调用回调DisposeDispose并且WaitOne(或者实际上就在之前 WaitOne)您的Timer回调可能会调用Invoke. Invoke正在阻塞并等待 UI 线程处理消息。但是,如果您的Stop方法被 UI 上的某些东西(即消息)调用,则意味着消息泵在WaitOne. 死锁

可以通过使用BeginInvoke切换Invoke来解决此问题。但是,您最终仍会阻止 UI 线程——在大多数情况下,阻止它处理有用的消息。

您的问题没有详细说明您要做什么,因此基本上不可能准确地或确定地告诉您如何解决您的问题。简短的回答:重新设计,这样您就不必等待。如果你仍然坚持这一点,我建议你问一个不同的问题,概述你想要完成什么,你已经尝试过什么,以及如何做才能做得更好。

于 2014-10-01T15:47:41.630 回答