Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance implications of BeginInvoke

I've inherited code where BeginInvoke is called from the main thread (not a background thread, which is usually the pattern). I am trying to understand what it actually does in this scenario.

Does the method being called in the BeginInvoke get in line of messages that come down to the window? The docs say asynchronously, so that is my assumption.

How does the framework prioritize when to kick off the method called by BeginInvoke?

Edit: The code looks like this:

System.Action<bool> finalizeUI = delegate(bool open)
{
    try
    {
        // do somewhat time consuming stuff
    }
    finally
    {
        Cursor.Current = Cursors.Default;
    }
};

Cursor.Current = Cursors.WaitCursor;
BeginInvoke(finalizeUI, true);

This is happening in the Form_Load event.

like image 662
AngryHacker Avatar asked Mar 18 '10 20:03

AngryHacker


1 Answers

edit

Now that we see the code, it's clear that this is just a way to move some initialization out of Form_Load but still have it happen before the user can interact with the form.

The call to BeginInvoke is inside Form_load, and is not called on another object, so this is a call to Form.BeginInvoke. So what's happening is this.

  1. Form_Load passes a delegate to Form.BeginInvoke, this puts a message in the form's message queue that is ahead of all user input messages. It sets the cursor to a wait cursor.
  2. Form_Load returns, and the rest of form initialization is allowed to complete, the form most likely becomes visible at this point.
  3. Once the code falls into the message pump, the first thing is sees in the queue is the delegate, so it runs that.
  4. as the delegate completes, it changes the cursor back to the normal cursor, and returns
  5. profit!

original post below


I depends on the object that you call BeginInvoke on. If the object is derived from Control then Control.BeginInvoke will run on the thread that created the control. See JaredPar's answer.

But there is another pattern for the use of BeginInvoke. if the object is a delegate, then BeginInvoke runs the callback on a separate thread, one that may be created specifically for that purpose.

public class Foo
{
    ...
    public Object Bar(object arg)
    {
       // this function will run on a separate thread.
    }
}

...

// this delegate is used to Invoke Bar on Foo in separate thread, this must
// take the same arguments and return the same value as the Bar method of Foo
public delegate object FooBarCaller (object arg);

...

// call this on the main thread to invoke Foo.Bar on a background thread
//
public IAsyncResult BeginFooBar(AsyncCallback callback, object arg)
{
   Foo foo = new Foo();
   FooBarCaller caller = new FooBarCaller (foo.Bar);
   return caller.BeginInvoke (arg);
}

This pattern is one reason that BeginInvoke is called from the main thread rather than from a background thread.

like image 87
John Knoeller Avatar answered Sep 20 '22 11:09

John Knoeller