control.BeginInvoke() fails to call the delegate
Asked Answered
O

1

2

I noticed that control.BeginInvoke(delegate) some times fail to call the delegate. I understand that BeginInvoke just creates a PostMessage and that message is handled by the application later (post message limit by default is 10,000). Given that our application is not very complex, Is there any other reason why it can fail to execute the delegate? My code is something like below.

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[]{});
    }
}
Ontiveros answered 7/6, 2011 at 19:25 Comment(6)
why is the signature for Bar not the same as DelagetBar? These should matchSalver
oh .. it was a typo. I have edited the post.Ontiveros
You're sure the Form has been completly loaded before calling BeginInvoke? social.msdn.microsoft.com/forums/en-US/winforms/thread/…Pavo
@Christian, Yes form is loaded. One of our user complained that the application is hung. Looking at the logs, we found out that Bar had be called every 5 seconds from past 7-8 hours and working properly before the user reported its hung.Ontiveros
Your executing flag does not do what you hope it does. The test-and-set operation you use is a fundamental threading race. You must use the lock statement to prevent two threads from simultaneously entering foo(). The five seconds delay will make it work most of the time. Until the machine gets heavily loaded.Courland
@Hans- you are right, there is a race in the above code. I verified the code we have & aparantly, I checked again using debugger that 'CallMeEveryFiveSeconds' is called by main thread. So, unless one of the POST messages is lost (which are generated by BeginInvoke) I don't see a race anymore. I have updated the example above.Ontiveros
S
0

The code looks fine to me as posted. If this does not match your code in use then I would suggest looking for one of the following:

1) If your consuming task takes longer then the FiveSeconds method to give the appearance of not being called every time

2) If the combination of the consuming task and Updating the UI results in the appearance of the method not being called every time

3) If any of the code not shown in the consuming task could alter the value of executing (or exit the method because it can be set to false)

Salver answered 7/6, 2011 at 20:24 Comment(1)
Thanks for the response, Based upon the logs I am sure that BeginInvoke() is not executing the delegate. I was using Invoke before when user complained more frequently the the UI hangs. But even after using BeginInvoke, UI hangs for the same user but way way less frequent .. and I noticed that in logs that "executing" flag is true ..Ontiveros

© 2022 - 2024 — McMap. All rights reserved.