Dispatcher.BeginInvoke: Cannot convert lambda to System.Delegate
Asked Answered
D

5

86

I'm trying to call System.Windows.Threading.Dispatcher.BeginInvoke. The signature of the method is this:

BeginInvoke(Delegate method, params object[] args)

I'm trying to pass it a Lambda instead of having to create a Delegate.

_dispatcher.BeginInvoke((sender) => { DoSomething(); }, new object[] { this } );

It's giving me a compiler error saying that I

can't convert the lambda to a System.Delegate.

The signature of the delegate takes an object as a parameter and returns void. My lambda matches this, yet it's not working. What am I missing?

Doorn answered 8/2, 2011 at 17:49 Comment(1)
Does this answer your question? Cannot convert lambda expression to type 'System.Delegate'Tuyere
C
74

Since the method takes a System.Delegate, you need to give it a specific type of delegate, declared as such. This can be done via a cast or a creation of the specified delegate via new DelegateType as follows:

_dispatcher.BeginInvoke(
     new Action<MyClass>((sender) => { DoSomething(); }),
     new object[] { this } 
  );

Also, as SLaks points out, Dispatcher.BeginInvoke takes a params array, so you can just write:

_dispatcher.BeginInvoke(
     new Action<MyClass>((sender) => { DoSomething(); }),
     this
  );

Or, if DoSomething is a method on this object itself:

_dispatcher.BeginInvoke(new Action(this.DoSomething));
Cluny answered 8/2, 2011 at 17:50 Comment(6)
But doesn't (x) => { DoSomething(); } match the signature of the delegate? I thought that's all I should have to specify.Doorn
@Micah: System.Delegate doesn't have a signature - it's just "any delegate" at all. You need to provide it a delegate type with a sig. that matches your usage.Cluny
@Reed But if in place of MyMethod(Action action) (and Action is a delegate) I can call MyMethod(() => { DoSomething(); }); Why can't I do the same thing for BeginInvoke?Doorn
@Micah: There actually isn't a signature for the delegate, which is what causes the issue. Invoke and BeginInvoke take a generic Delegate object, which can represent a method of any signature. Under normal circumstances (where a delegate is strongly typed to a particular signature), the compiler can infer the specific delegate type. This is why you're able to get away with omitting the delegate type in other scenarios. However, since there is no actual delegate type here, the compiler does not have a reasonable basis (or, really, even a means) to use to select a delegate type.Blepharitis
@Micah: Because BeginInvoke isn't declared as BeginInvoke(Action ..), but rather BeginInvoke(System.Delegate, ..) This allows it to use ANY delegate type, but you must specify it explicitly.Cluny
I'd love to know why they did this! Invoke works in a sane way: Invoke(()=>{}); Why does BeginInvoke force you to do all this? I'll give all DispatcherObjects a comfortable extension method anyways, but still, WHY?Phelloderm
F
76

Shorter:

_dispatcher.BeginInvoke((Action)(() => DoSomething()));
Fontenot answered 6/10, 2011 at 1:50 Comment(3)
Even shorter: I don't think you need the braces {} and semicolon around the expression.Palliative
You don't even need (), so it can be _dispatcher.BeginInvoke((Action)(DoSomething));Shrew
Or even _dispatcher.BeginInvoke(DoSomething);Calen
C
74

Since the method takes a System.Delegate, you need to give it a specific type of delegate, declared as such. This can be done via a cast or a creation of the specified delegate via new DelegateType as follows:

_dispatcher.BeginInvoke(
     new Action<MyClass>((sender) => { DoSomething(); }),
     new object[] { this } 
  );

Also, as SLaks points out, Dispatcher.BeginInvoke takes a params array, so you can just write:

_dispatcher.BeginInvoke(
     new Action<MyClass>((sender) => { DoSomething(); }),
     this
  );

Or, if DoSomething is a method on this object itself:

_dispatcher.BeginInvoke(new Action(this.DoSomething));
Cluny answered 8/2, 2011 at 17:50 Comment(6)
But doesn't (x) => { DoSomething(); } match the signature of the delegate? I thought that's all I should have to specify.Doorn
@Micah: System.Delegate doesn't have a signature - it's just "any delegate" at all. You need to provide it a delegate type with a sig. that matches your usage.Cluny
@Reed But if in place of MyMethod(Action action) (and Action is a delegate) I can call MyMethod(() => { DoSomething(); }); Why can't I do the same thing for BeginInvoke?Doorn
@Micah: There actually isn't a signature for the delegate, which is what causes the issue. Invoke and BeginInvoke take a generic Delegate object, which can represent a method of any signature. Under normal circumstances (where a delegate is strongly typed to a particular signature), the compiler can infer the specific delegate type. This is why you're able to get away with omitting the delegate type in other scenarios. However, since there is no actual delegate type here, the compiler does not have a reasonable basis (or, really, even a means) to use to select a delegate type.Blepharitis
@Micah: Because BeginInvoke isn't declared as BeginInvoke(Action ..), but rather BeginInvoke(System.Delegate, ..) This allows it to use ANY delegate type, but you must specify it explicitly.Cluny
I'd love to know why they did this! Invoke works in a sane way: Invoke(()=>{}); Why does BeginInvoke force you to do all this? I'll give all DispatcherObjects a comfortable extension method anyways, but still, WHY?Phelloderm
R
10

Using Inline Lambda...

Dispatcher.BeginInvoke((Action)(()=>{
  //Write Code Here
}));
Rollick answered 7/1, 2016 at 16:10 Comment(0)
P
8

If you reference System.Windows.Presentation.dll from your project and add using System.Windows.Threading then you can access an extension method that allows you to use the lambda syntax.

using System.Windows.Threading;

...

Dispatcher.BeginInvoke(() =>
{
});
Paraphrastic answered 24/11, 2014 at 11:16 Comment(3)
I cannot get this to work. Could you go a little more into detail?Blowup
I've added a simple example. Remember to reference System.Windows.Presentation.dllParaphrastic
That's exactly what I but now it works...weird. Maybe I did something wrong last time.Blowup
L
5

We create extension methods for this. E.g.

public static void BeginInvoke(this Control control, Action action)
    => control.BeginInvoke(action);

Now we can call it from within a form: this.BeginInvoke(() => { ... }).

Lira answered 17/5, 2018 at 17:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.