Daniel Peñalba
Daniel Peñalba

Reputation: 31847

Control.Invoke() hangs application

I'm showing an animation while my control is loading the data. When the thread finishes, I hide the animation and show the control. So I'm executing this code from a thread:

protected void InvokeEnableBackControl()
{
    if (this.InvokeRequired)
    {                
        this.Invoke(new OpHandler(EnableBackControl));
    }
    else
    {
        EnableBackControl();
    }
}

Sometimes, when I execute this code, the main thread gets hanged in the following code:

protected virtual void EnableBackControl()
{
    if (overlayAnimation.TargetControl != null)
    {
        overlayAnimation.TargetControl.BringToFront();
    }

    overlayAnimation.SendToBack();
    overlayAnimation.Enabled = false;
    overlayAnimation.Visible = false;                      

}

I'm not sure if it's hanged setting the Enable or Visible property. Do you know any circumstance that may hand the application calling these properties from a Control.Invoke?

Upvotes: 12

Views: 19315

Answers (5)

alireza amini
alireza amini

Reputation: 1742

You have to use BeginInvoke inested Invoke see this Link

Upvotes: 0

Steed
Steed

Reputation: 287

What I discovered is that the actual drawing/painting of controls can be quite slow, esp if you have a lot of them and/or use double buffering for smooth refresh. I was using BeginInvoke to update a listview control from data I was receiving from a socket. At times the updates were happening so fast that it was freezing the app up. I solved this by writing everything I received in the sockets async receive to a queue, and then in a seperate thread dequeuing the data and using BeginUpdate and EndUpdate on the listview and doing all the outstanding updates in between. This cut out a ton of the extra redrawing and made the app a lot more responsive.

Upvotes: 0

SqlRyan
SqlRyan

Reputation: 33914

I've run into problems before when I'm executing .Invoke on a background thread while my main thread is still busy - this gives the impression that the app is hung, because the .Invoke just sits there, waiting for the main thread to respond that it's paying attention. Possible causes:

  • Your main thread is blocked waiting for something
  • Your main form currently had a modal dialog up, so it's not listening to new requests
  • Your main thread is spinning, either continually checking if something is finished or doing new work. In my case, the main thread spent the first minute spinning up background threads in a tight loop, so it wasn't listening for any .Invoke requests from background threads.

When you attach the debugger, pay special attention to what your main control MessagePump thread is doing - I suspect its lack of attention is the cause of your trouble. If you identify that it's a tight loop in your main thread that's not responding, try inserting a .DoEvents in the loop, which will pause execution and force the main thread to empty the message pump and route any outstanding requests.

Upvotes: 9

bentsai
bentsai

Reputation: 3133

Note that Control.Invoke is synchronous, so it will wait for EnableBackControl() to return. Consider using Control.BeginInvoke, which you can "fire and forget."

See this answer: What's the difference between Invoke() and BeginInvoke()

Upvotes: 27

Andrey
Andrey

Reputation: 60055

Run in debug, make app hang and then pause debug in Visual Studio and inspect threads.

Upvotes: 4

Related Questions