1

C# windows forms VS 2013 OS:Win7

I am having an interesting problem where invokeRequired is true but when I call beginInvoke() it never executes and the window never closes.

However when I remove beingInvoke() altogether the window closes ok.

     public void CloseMyForm()
            {
//if I remove this if block altogether including beingInvoke() the window closes ok
                if ( !this.IsDisposed && this.InvokeRequired && this.IsHandleCreated )
                {
                    log("callin begininvoke()"); //this is logged correctly 

                    this.BeginInvoke((MethodInvoker)delegate() { CloseMyForm(); });
                    return;
                }
               log("outside of begin invoke"); //this is never logged
               this.Close();
            }

CloseMyForm is called by a separate thread which is created like this at the startup. Please note this is not the main window but a separate window open from the main form.

Thread connectThread = new Thread(new ThreadStart(CheckWhenToCloseMyForm)); 

    public void CheckWhenToCloseMyForm()
    {
        while (true)
        {
            CallSomeFunc();
            CallSomeFunc1();
            if (allconditionsmet)
            {
                System.Threading.Thread.Sleep(1000);
                CloseMyForm();
break;

            }        
        }       
    }
bsobaid
  • 955
  • 1
  • 16
  • 36
  • What is calling `CloseMyForm` initially? – David Pine May 02 '16 at 18:49
  • You probably shouldn't be calling a method like this from a background thread. – LarsTech May 02 '16 at 18:49
  • CloseMyForm is called by a separete thread initially. Thread connectThread = new Thread(new ThreadStart(CheckWhenTo CloseMyForm)); The CheckWhenToCloseMyForm() has a while(true) loop that calls CloseMyForm after certain conditions are met. – bsobaid May 02 '16 at 19:15

2 Answers2

2

The BeginInvoke is made available via the base Control class.

Executes a delegate asynchronously on the thread that the control's underlying handle was created on

If the InvokedRequired property is actually true, that means "the caller must call an invoke method when making method calls to the control because the caller is on a different thread than the one the control was created on".

It looks like you're incorrectly calling BeginInvoke, you should try calling Invoke instead.

Executes the specified delegate on the thread that owns the control's underlying window handle

public void CloseMyForm()
{
    if (!this.IsDisposed && this.InvokeRequired && this.IsHandleCreated)
    {
        log("calling invoke()");
        this.Invoke((MethodInvoker)delegate() { CloseMyForm(); });
    }
    else
    {
        log("outside of invoke"); // this is never logged
        this.Close();
    }
}

Check out this neat little extension method that could help simplify this. With this you could write your close method like this instead.

public void CloseMyForm()
{
    this.ThreadSafeInvoke(() => this.Close());
}
David Pine
  • 23,787
  • 10
  • 79
  • 107
  • unfortunately it did not help. the window still does not close – bsobaid May 02 '16 at 19:23
  • What is calling `CloseMyForm` externally? – David Pine May 02 '16 at 19:25
  • CloseMyForm is called by a separete thread initially. Thread connectThread = new Thread(new ThreadStart(CheckWhenTo CloseMyForm)); The CheckWhenToCloseMyForm() has a while(true) loop that calls CloseMyForm after certain conditions are met. – bsobaid May 02 '16 at 19:26
  • Abandon all hope, why would you spin up an entirely new thread for that - "Jeffrey Richter's face would be bright red"! http://stackoverflow.com/questions/7480359/should-i-use-invoke-or-synchronizationcontext-to-update-form-controls-from-anoth or http://stackoverflow.com/questions/11386576/c-sharp-opening-a-form-then-closing-it-from-another-method – David Pine May 02 '16 at 19:29
  • Its an existing application, I cant really change much, – bsobaid May 02 '16 at 19:31
  • yeah, the same form which we are trying to close. – bsobaid May 02 '16 at 19:39
0

Okay, now that you have provided this snippet I understand the issue.

Thread connectThread = new Thread(new ThreadStart(CheckWhenToCloseMyForm)); 

public void CheckWhenToCloseMyForm()
{
    while (true)
    {
        CallSomeFunc();
        CallSomeFunc1();
        if (allconditionsmet)
        {
            System.Threading.Thread.Sleep(1000);
            CloseMyForm()
        }        
    }       
}

In your while loop you need to break or return after you invoke CloseMyForm. That's it...very simple. You can use either BeginInvoke or Invoke.

David Pine
  • 23,787
  • 10
  • 79
  • 107
  • really sorry, actually I do have a break that I missed when I was posting it. I have edited code to show the break; statement – bsobaid May 02 '16 at 20:49