首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Invoke()被阻塞

Invoke()被阻塞
EN

Stack Overflow用户
提问于 2008-11-13 14:55:07
回答 4查看 13.4K关注 0票数 23

我的应用程序GUI会不时地停止重新绘制。有很多线程正在触发各种事件(比如定时器或网络数据就绪等)。此外,还有许多控件正在订阅这些事件。因此,所有事件处理程序都玩InvokeRequired/Invoke游戏。现在我明白了,当GUI冻结时,很多线程都在等待Invoke()返回。看起来消息泵停止抽水了。处理程序如下所示:

代码语言:javascript
复制
private void MyEventHandler( object sender, EventArgs e ) {
    if ( InvokeRequired ) {
        Invoke( new EventHandler( MyEventHandler ), sender, e );
        return;
    }

    SetSomeStateVariable();
    Invalidate();
}

有什么想法吗?

解决方案: BeginInvoke()。看起来你应该总是使用BeginInvoke(),如果你有很多的交叉线程事件...

谢谢。

谢谢大家。

编辑:看起来BeginInvoke()真的解决了这个问题。直到现在才会结冰。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2008-11-13 14:57:59

Invoke将一直等待,直到GUI线程处理完事件。如果希望它是异步的,请使用BeginInvoke()

票数 33
EN

Stack Overflow用户

发布于 2008-11-13 14:57:38

也许是死结?您是否确保在持有锁的同时不会触发事件?

你能在附加调试器的情况下看到这个吗?如果是这样的话,让它冻结,然后点击“暂停”按钮-看看UI线程在做什么。

请注意,如果您能够使用BeginInvoke而不是Invoke,生活就会更容易一些,因为它不会阻塞。

还要注意的是,您不需要“新的EventHandler”位--只要

代码语言:javascript
复制
Invoke((EventHandler) MyEventHandler, sender, e);

应该没问题。

票数 6
EN

Stack Overflow用户

发布于 2008-11-13 15:57:44

从这个问题中,我可以看到你不会得到任何可以立即解决这个问题的答案,因为他们中的大多数都需要你调试事件,而且这种情况发生得如此之少,以至于几乎不可能发生。因此,我建议您进行一些代码更改,以帮助您识别该领域的罪魁祸首。

我建议您创建一个静态类,它的唯一目的是处理所有的调用。我建议这个类有一个接受Control的方法,(在上面调用Invoke )一个Action (要调用的方法)和一个description (包含你需要知道的信息来识别这个方法以及它要做什么)。

在此方法的主体中,我建议您将此信息(方法、描述)排入队列并立即返回。

队列应该由单个线程提供服务,该线程从队列中弹出操作/消息对,在一对属性中记录当前时间和操作的描述,然后调用Action ()。操作返回时,描述和时间将被清除(您的DateTime可以为空,也可以将其设置为DateTime.Max)。请注意,由于所有调用都逐个编组到UI线程上,因此在这里由单个线程为队列提供服务不会造成任何损失。

现在,这就是我们要说的重点。我们的调用类应该有一个心跳System.Threading.Timer线程。这不应该是一个windows.forms.timer对象,因为它在UI线程上运行(当UI被阻塞时,它将被阻塞!)。

此计时器的任务是定期查看调用当前操作的时间。如果DateTime.Now - BeginTime > X,心跳计时器将决定此操作已被阻止。心跳计时器将记录(无论您如何记录)为该操作记录的描述。现在,您已经记录了锁定UI时发生的事情,并且可以更好地对其进行调试。

我知道这不能解决你的问题,但至少通过这样做,你可以对你被阻塞时发生的事情有一个很好的了解。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/287142

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档