Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous method in Invoke call

People also ask

What is used to call an anonymous method?

An Anonymous method is defined using the delegate keyword and the user can assign this method to a variable of the delegate type. Important Points: This method is also known as inline delegate. Using this method you can create a delegate object without writing separate methods.

What are anonymous methods?

Anonymous method is a block of code, which is used as a parameter for the delegate. An anonymous method can be used anywhere. A delegate is used and is defined in line, without a method name with the optional parameters and a method body. The scope of the parameters of an anonymous method is the anonymous-method-block.

Why anonymous method is used in C#?

Anonymous methods provide a technique to pass a code block as a delegate parameter. Anonymous methods are the methods without a name, just the body. You need not specify the return type in an anonymous method; it is inferred from the return statement inside the method body.


Because Invoke/BeginInvoke accepts Delegate (rather than a typed delegate), you need to tell the compiler what type of delegate to create ; MethodInvoker (2.0) or Action (3.5) are common choices (note they have the same signature); like so:

control.Invoke((MethodInvoker) delegate {this.Text = "Hi";});

If you need to pass in parameters, then "captured variables" are the way:

string message = "Hi";
control.Invoke((MethodInvoker) delegate {this.Text = message;});

(caveat: you need to be a bit cautious if using captures async, but sync is fine - i.e. the above is fine)

Another option is to write an extension method:

public static void Invoke(this Control control, Action action)
{
    control.Invoke((Delegate)action);
}

then:

this.Invoke(delegate { this.Text = "hi"; });
// or since we are using C# 3.0
this.Invoke(() => { this.Text = "hi"; });

You can of course do the same with BeginInvoke:

public static void BeginInvoke(this Control control, Action action)
{
    control.BeginInvoke((Delegate)action);
}

If you can't use C# 3.0, you could do the same with a regular instance method, presumably in a Form base-class.


Actually you do not need to use delegate keyword. Just pass lambda as parameter:

control.Invoke((MethodInvoker)(() => {this.Text = "Hi"; }));

myControl.Invoke(new MethodInvoker(delegate() {...}))

You need to create a delegate type. The keyword 'delegate' in the anonymous method creation is a bit misleading. You are not creating an anonymous delegate but an anonymous method. The method you created can be used in a delegate. Like this:

myControl.Invoke(new MethodInvoker(delegate() { (MyMethod(this, new MyEventArgs(someParameter)); }));

For the sake of completeness, this can also be accomplished via an Action method/anonymous method combination:

//Process is a method, invoked as a method group
Dispatcher.Current.BeginInvoke((Action) Process);
//or use an anonymous method
Dispatcher.Current.BeginInvoke((Action)delegate => {
  SomeFunc();
  SomeOtherFunc();
});

I had problems with the other suggestions because I want to sometimes return values from my methods. If you try to use MethodInvoker with return values it doesn't seem to like it. So the solution I use is like this (very happy to hear a way to make this more succinct - I'm using c#.net 2.0):

    // Create delegates for the different return types needed.
    private delegate void VoidDelegate();
    private delegate Boolean ReturnBooleanDelegate();
    private delegate Hashtable ReturnHashtableDelegate();

    // Now use the delegates and the delegate() keyword to create 
    // an anonymous method as required

    // Here a case where there's no value returned:
    public void SetTitle(string title)
    {
        myWindow.Invoke(new VoidDelegate(delegate()
        {
            myWindow.Text = title;
        }));
    }

    // Here's an example of a value being returned
    public Hashtable CurrentlyLoadedDocs()
    {
        return (Hashtable)myWindow.Invoke(new ReturnHashtableDelegate(delegate()
        {
            return myWindow.CurrentlyLoadedDocs;
        }));
    }

I like to use Action in place of MethodInvoker, it is shorter and looks cleaner.

Invoke((Action)(() => {
    DoSomething();
}));

// OR

Invoke((Action)delegate {
    DoSomething();
});

Eg.

// Thread-safe update on a form control
public void DisplayResult(string text){
    if (txtResult.InvokeRequired){
        txtResult.Invoke((Action)delegate {
            DisplayResult(text);
        });
        return;
    }

    txtResult.Text += text + "\r\n";
}