Anonymous method in Invoke call

135,788

Solution 1

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.

Solution 2

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

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

Solution 3

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

Solution 4

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

Solution 5

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();
});
Share:
135,788
Duncan
Author by

Duncan

.NET Architect/Developer (C#) - ASP.NET MVC

Updated on April 29, 2020

Comments

  • Duncan
    Duncan about 4 years

    Having a bit of trouble with the syntax where we want to call a delegate anonymously within a Control.Invoke.

    We have tried a number of different approaches, all to no avail.

    For example:

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

    where someParameter is local to this method

    The above will result in a compiler error:

    Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type

  • uzay95
    uzay95 over 14 years
    How can i pass parameters to your first solution in this answer? I meant this solution: control.Invoke((MethodInvoker) delegate {this.Text = "Hi";});
  • yairr
    yairr over 11 years
    Why does the Extension Method get invoked without having to do an Explicit cast to Action?
  • RoboJ1M
    RoboJ1M over 8 years
    Because the compiler can infer that from the usage.
  • RoboJ1M
    RoboJ1M over 8 years
    It's the same as being able to do Form.Load += Loader() instead of the old Form.Load += new EventHandler(Loader())
  • Jinjinov
    Jinjinov over 4 years
    Invoke((Action) Process); is the best answer, thank you!