bsobaid
bsobaid

Reputation: 975

InvokeRequired=true but BeginInvoke fails causing freeze

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;

            }        
        }       
    }

Upvotes: 1

Views: 1234

Answers (2)

David Pine
David Pine

Reputation: 24525

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.

Upvotes: 0

David Pine
David Pine

Reputation: 24525

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());
}

Upvotes: 2

Related Questions