首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BeginInvoke()呼叫延迟

BeginInvoke()呼叫延迟
EN

Stack Overflow用户
提问于 2013-11-13 20:17:35
回答 1查看 1.1K关注 0票数 1

我和Control.BeginInvoke()有一个问题,不是每次都会发生。它似乎工作了5次左右,然后成为50/50的成功率之后。

正在发生的事情是,我将在已经创建和显示的控件上调用BeginInvoke(),并且调用不会立即在GUI线程上执行。调用线程会立即从BeginInvoke()返回并继续其业务。在控件上执行另一个BeginInvoke()之前,委托不会在GUI线程上执行。然后,就好像它意识到它有一些事情要做,并最终做了它。这可能会超过10分钟。

下面是执行不立即执行委托的BeginInvoke()的代码:

代码语言:javascript
复制
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()的按钮。

代码语言:javascript
复制
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
}

最后,这里是输出:

代码语言:javascript
复制
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()出现这种延迟行为,我能做些什么来更好地调试它呢?

其他注释:

  1. 这些方法属于UserControl对象的实例
  2. UserControl对象已经存在,并在代码运行之前显示了几分钟,即控制句柄应该存在。
  3. 我曾多次像这样成功地使用过BeginInvoke()
  4. 在运行委托期间,GUI似乎是完全响应的。GUI控件正在更新,我可以导航应用程序等。

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-11-14 13:36:09

感谢Adam的评论,我相信我已经找到了问题的根源。确实有大量的BeginInvoke()调用正在执行,但这并不明显。我有另一个控件,它接收来自后台线程的大量更新。不足以在正常情况下导致问题,但问题是越来越多的控件实例都在接收更新并执行BeginInvoke()来更新GUI。

控件数量不断增加的原因是,当从该视图导航时,应该销毁实例,并在返回该视图时重新创建实例。然而,控件并没有被销毁,因为它们注册了来自长期存在的类实例的更新事件,并且在从窗体中删除控件时没有从事件中注销。这导致长期存在的类保存对所讨论的UserControl实例的引用,所有实例都将继续处理事件并更新GUI,即使它们不再可见。

因此,即使GUI在某种程度上仍然具有响应性,它也无法完成所有传入的异步调用。我读过这里SendMessage消息实际上并不像PostMessage消息那样被添加到消息队列中,而是由消息泵直接执行,并且比PostMessage填充的消息队列具有更高的优先级。因此,如果通过SendMessage事件处理普通按钮单击和SendMessage事件,并在消息队列上处理BeginInvoke()调用,我可以看到这种情况是如何发生的。

感谢所有的帮助和快速的建议!谁知道我找这个花了多久!

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

https://stackoverflow.com/questions/19963476

复制
相关文章

相似问题

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