【问题标题】:control.BeginInvoke() fails to call the delegatecontrol.BeginInvoke() 调用委托失败
【发布时间】:2011-09-10 08:40:29
【问题描述】:

我注意到 control.BeginInvoke(delegate) 有时无法调用委托。我知道 BeginInvoke 只是创建一个 PostMessage 并且该消息稍后由应用程序处理(默认情况下发布消息限制为 10,000)。鉴于我们的应用程序不是很复杂,是否还有其他原因导致它无法执行委托?我的代码如下所示。

class MyClass : Form{

    private bool executing = false;
    private delegate void DelegateBar(string info, int total, bool status, object obj);
    private void Bar(string info, int total, bool status, object obj){
        log("Enterning Bar");
        // Update something on UI
        executing = false;
        log("Exiting Bar");
    }
    public void foo(){
        log("Entering Foo");
        executing = true;
            try{
            // do something over the network
            }catch(Exception e){
                // probably network down. Lets not worry about it
            }
        DelegateBar barPtr = new DelegateBar(Bar);
        // Update UI .. call on form : form is a control
        this.BeginInvoke(barPtr, new object[] {"someInfo", 3, false, null});
        log("Exiting Fool");
    }

    public void callMeEveryFiveSeconds(){
        if(!executing) foo();
    }

    private delegate void DelegateCallMe();

    // execute every 5 seconds.
    private void timer1_Tick(object sender, EventArgs e)
    {
        Delegate del = new DelegateCallMe(callMeEveryFiveSeconds);
        // appoligies if syntax is not right, it to convey the idea that callMeEveryFiveSeconds is called on the main thread (asynchronously)
        this.beginInvoke(del, new object[]{});
    }
}

【问题讨论】:

  • 为什么 Bar 的签名和 DelagetBar 的签名不一样?这些应该匹配
  • 哦..这是一个错字。我已经编辑了帖子。
  • 您确定在调用 BeginInvoke 之前表单已完全加载? social.msdn.microsoft.com/forums/en-US/winforms/thread/…
  • @Christian,是的,表单已加载。我们的一位用户抱怨应用程序挂起。查看日志,我们发现 Bar 在过去 7-8 小时内每 5 秒被调用一次,并且在用户报告其挂起之前正常工作。
  • 你的 executing 标志没有做你希望的事情。您使用的测试和设置操作是基本的线程竞赛。您必须使用 lock 语句来防止两个线程同时进入 foo()。五秒钟的延迟将使它在大部分时间都可以工作。直到机器负载很重。

标签: c# delegates begininvoke


【解决方案1】:

发布的代码对我来说看起来不错。如果这与您使用的代码不匹配,那么我建议您寻找以下之一:

1) 如果您的消费任务需要更长的时间,那么 FiveSeconds 方法会显示每次都不会被调用

2) 如果消费任务和更新 UI 的组合导致方法的出现不是每次都被调用

3) 如果任何未在消费任务中显示的代码可能会改变执行的值(或退出该方法,因为它可以设置为 false)

【讨论】:

  • 感谢您的回复,根据日志,我确信 BeginInvoke() 没有执行委托。当用户更频繁地抱怨 UI 挂起时,我正在使用 Invoke。但即使在使用 BeginInvoke 之后,UI 仍会为同一用户挂起,但频率要低得多.. 我注意到在日志中“正在执行”标志为 true ..
猜你喜欢
  • 2012-02-17
  • 2010-12-20
  • 1970-01-01
  • 2018-09-21
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多