我和Control.BeginInvoke()有一个问题,不是每次都会发生。它似乎工作了5次左右,然后成为50/50的成功率之后。
正在发生的事情是,我将在已经创建和显示的控件上调用BeginInvoke(),并且调用不会立即在GUI线程上执行。调用线程会立即从BeginInvoke()返回并继续其业务。在控件上执行另一个BeginInvoke()之前,委托不会在GUI线程上执行。然后,就好像它意识到它有一些事情要做,并最终做了它。这可能会超过10分钟。
码
下面是执行不立即执行委托的BeginInvoke()的代码:
protected void DisplayPrompt(PromptData promptData)
{
Debug.WriteLine(DateTime.Now + ": Entering DisplayPrompt: " + Thread.CurrentThread.Name);
this.CurrentPrompt = promptData;
if (this.InvokeRequired)
{
Debug.WriteLine(DateTime.Now + ": Before BeginInvoke of DisplayPrompt: " + Thread.CurrentThread.Name);
this.BeginInvoke(new Action(() => this.DisplayPrompt(promptData)));
Debug.WriteLine(DateTime.Now + ": After BeginInvoke of DisplayPrompt: " + Thread.CurrentThread.Name);
return;
}
// The rest of the method goes here
}通过消息泵启动被调用的方法似乎是在执行以下代码时。当我厌倦了等待上面的委托被执行之后,这段代码就会被执行,然后我按下一个最终调用ClearPrompt()的按钮。
protected void ClearPrompt()
{
Debug.WriteLine(DateTime.Now + ": Entering ClearPrompt: " + Thread.CurrentThread.Name);
this.CurrentPrompt = null;
if (this.InvokeRequired)
{
Debug.WriteLine(DateTime.Now + ": Before BeginInvoke of ClearPrompt: " + Thread.CurrentThread.Name);
this.BeginInvoke(new Action(() => this.ClearPrompt()));
Debug.WriteLine(DateTime.Now + ": After BeginInvoke of ClearPrompt: " + Thread.CurrentThread.Name);
return;
}
// The rest of the method goes here
}最后,这里是输出:
11/13/2013 1:16:49 PM: Entering DisplayPrompt: BatchStateMachine
11/13/2013 1:16:49 PM: Before BeginInvoke of DisplayPrompt: BatchStateMachine
11/13/2013 1:16:49 PM: After BeginInvoke of DisplayPrompt: BatchStateMachine
The thread 0x998 has exited with code 0 (0x0).
The thread 0x1174 has exited with code 0 (0x0).
11/13/2013 1:27:01 PM: Entering ClearPrompt: BatchStateMachine
11/13/2013 1:27:01 PM: Before BeginInvoke of ClearPrompt: BatchStateMachine
11/13/2013 1:27:01 PM: After BeginInvoke of ClearPrompt: BatchStateMachine
11/13/2013 1:27:01 PM: Entering DisplayPrompt:
11/13/2013 1:27:01 PM: Entering ClearPrompt: 这是1:27:01 PM上的第二个1:27:01 PM,也是GUI最终运行委托的地方。
问题:,所以我想问题是,什么会导致BeginInvoke()出现这种延迟行为,我能做些什么来更好地调试它呢?
其他注释:
UserControl对象的实例UserControl对象已经存在,并在代码运行之前显示了几分钟,即控制句柄应该存在。BeginInvoke()谢谢!
发布于 2013-11-14 13:36:09
感谢Adam的评论,我相信我已经找到了问题的根源。确实有大量的BeginInvoke()调用正在执行,但这并不明显。我有另一个控件,它接收来自后台线程的大量更新。不足以在正常情况下导致问题,但问题是越来越多的控件实例都在接收更新并执行BeginInvoke()来更新GUI。
控件数量不断增加的原因是,当从该视图导航时,应该销毁实例,并在返回该视图时重新创建实例。然而,控件并没有被销毁,因为它们注册了来自长期存在的类实例的更新事件,并且在从窗体中删除控件时没有从事件中注销。这导致长期存在的类保存对所讨论的UserControl实例的引用,所有实例都将继续处理事件并更新GUI,即使它们不再可见。
因此,即使GUI在某种程度上仍然具有响应性,它也无法完成所有传入的异步调用。我读过这里,SendMessage消息实际上并不像PostMessage消息那样被添加到消息队列中,而是由消息泵直接执行,并且比PostMessage填充的消息队列具有更高的优先级。因此,如果通过SendMessage事件处理普通按钮单击和SendMessage事件,并在消息队列上处理BeginInvoke()调用,我可以看到这种情况是如何发生的。
感谢所有的帮助和快速的建议!谁知道我找这个花了多久!
https://stackoverflow.com/questions/19963476
复制相似问题