简体   繁体   English

ManualResetEvent.WaitOne卡住了GUI

[英]ManualResetEvent.WaitOne stuck the GUI

I have a Timer that does several things 我有一个可以做几件事的Timer

private System.Threading.Timer _xTimer = new System.Threading.Timer(new TimerCallback(XTimerHandler), null, 0, _xTimerPollingInterval);

private void XTimerHandler(object param)
{
    //some code.
}

I have a function which stops the timer: 我有一个停止计时器的功能:

private void Stop()
{
     //some code.
     if (_xTimer != null)
     {
        ManualResetEvent timerDisposeHandler = new ManualResetEvent(false);
        _xTimer.Dispose(timerDisposeHandler);
        _dataProcessingTimer = null;
        //wait for dispose end.
        timerDisposeHandler.WaitOne();

     }
}

Something very strange is going on! 发生了非常奇怪的事情!

Sometimes all the GUI hangs on timerDisposeHandler.WaitOne(); 有时,所有的GUI都挂在timerDisposeHandler.WaitOne(); (but only sometimes, and I could not see a pattern that repeats itself where it happens, it just dynamically) (但仅在某些情况下,并且我看不到会在发生这种情况时重复出现的模式,只是动态地重复出现)

Has anyone encountered a similar problem and solved it? 有没有人遇到过类似的问题并解决了?

Blocking the UI is effectively unsupported. 实际上不支持阻止UI。 While there are wait routines that are "supported" on the UI thread (which means they recognize there is a message pump and pump messages while you're waiting) it's not a good idea to do in general. 虽然有一些是在UI线程上“支持”等程序(这意味着他们承认有一个消息泵,而你等待泵消息)这不是一个好主意,一般做。

First, you're blocking the UI. 首先,您要阻止UI。 Yes, some message pumping can occur in certain circumstances, but do you really want the UI thread processing messages and waiting? 是的,在某些情况下可能会发生一些消息泵送,但是您真的想要UI线程处理消息等待吗? Recipe for disaster if you're not really , really careful. 如果您不是真的 非常谨慎,请为灾难准备食谱。

Let's take a simple scenario. 让我们来看一个简单的场景。 Let's say that you've done your due diligence when writing your Timer callback (because you've chosen System.Threading.Timer and not "System.Windows.Forms.Timer" which actually runs the Tick event handler on the UI thread) and have chosen to marshal data back to the UI thread with Control.Invoke (or Dispatcher.Invoke with WPF, you haven't specified what type of Windows application you're talking about). 假设您在编写Timer回调时已经完成了尽职调查(因为您选择了System.Threading.Timer而不是实际上在UI线程上运行Tick事件处理程序的“ System.Windows.Forms.Timer”),并且已选择使用Control.Invoke (或使用WPF的Dispatcher.Invoke将数据Control.Invoke送回UI线程,您尚未指定要使用的Windows应用程序类型。 Conceptually you've got a Stop method that disposes the Timer and stops callbacks. 从概念上讲,您有一个Stop方法,该方法处理Timer并停止回调。 The Dispose methods for Timer are documented as saying that the callback can be called after Dispose is called and thus a race condition, but also, there may be a callback being invoked at the same time you called Dispose . 用于TimerDispose方法的文档记录为,可以在调用Dispose并因此形成竞争条件后调用该回调,但是在调用Dispose同时,可能还会调用一个回调。 Both of these scenarios mean that between Dispose and WaitOne (or really just before WaitOne ) your Timer callback may make that call to Invoke . 这两种情况都意味着在DisposeWaitOne之间(或实际上 WaitOne 之前 ),您的Timer回调可能会调用Invoke Invoke is blocking and waits for the UI thread to process the message. Invoke正在阻止,并等待UI线程处理消息。 But, if your Stop method was invoked by something on the UI (ie a message) that means the message pump is blocked on WaitOne . 但是,如果您的Stop方法是由UI上的某项(即消息)调用的,则意味着消息泵在WaitOne上被阻止。 Deadlock . 死锁

You could, possibly , fix this simply by switching out Invoke with BeginInvoke . 可以通过仅使用BeginInvoke切换Invoke来解决此问题。 But, you're still ultimately blocking the UI thread--keeping it, in most cases, from processing useful messages. 但是,您仍然最终仍会阻止UI线程-在大多数情况下,禁止它处理有用的消息。

Your question does not go into detail into what you're trying to do, so it's basically impossible to tell you exactly , or with any certainty, what to do to solve your problem. 你的问题不细讲到你想要做什么,所以基本上不可能确切地告诉你,或者有任何把握,怎样做才能解决您的问题。 Short answer: redesign so you don't have to wait. 简短答案:重新设计,因此您不必等待。 If you're still stuck on that, I'd suggest asking a different question outlining what you want to accomplish, what you've tried, and what to do to do it better. 如果您仍然坚持这样做,建议您提出一个不同的问题,概述您想要完成的工作,尝试过的工作以及如何做得更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ManualResetEvent.WaitOne()导致AccessViolation - ManualResetEvent.WaitOne() causes AccessViolation ManualResetEvent.WaitOne()返回false而不超时? - ManualResetEvent.WaitOne() returning false without timeout? 如何继续前进之前等待ManualResetEvent.WaitOne()到达? - How to wait for ManualResetEvent.WaitOne() to be reached before moving on? ManualResetEvent.WaitOne始终挂在ASP.NET MVC中 - ManualResetEvent.WaitOne is always hanging in ASP.NET MVC ManualResetEvent.WaitOne()抛出NullReferenceException:对象引用未设置为对象的实例 - ManualResetEvent.WaitOne() throws NullReferenceException: Object reference not set to an instance of an object 如何为包含ManualResetEvent.WaitOne()的异步(套接字)代码编写单元测试? - How to write unit test for asynchronous (socket) code that includes ManualResetEvent.WaitOne()? 如果在Set()之后立即调用Reset(),则ManualResetEvent.WaitOne()不会返回 - ManualResetEvent.WaitOne() doesn't return if Reset() is called immediately after Set() C# - 阻塞主线程直到从线程执行 ManualResetEvent.WaitOne() - C# - Block master-thread until slave-thread executed ManualResetEvent.WaitOne() WaitOne()不会在ManualResetEvent中等待 - WaitOne() doesnot wait in ManualResetEvent ManualResetEvent WaitOne没有解锁 - ManualResetEvent WaitOne not unblocking
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM