Dispatcher.BeginInvoke:无法将lambda转换为System.Delegate


81

我正在打电话System.Windows.Threading.Dispatcher.BeginInvoke。该方法的签名是这样的:

BeginInvoke(Delegate method, params object[] args)

我正在尝试将其传递给Lambda,而不必创建委托。

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

它给我一个编译器错误,说我

无法将lambda转换为System.Delegate。

委托的签名将对象作为参数并返回void。我的lambda与此匹配,但无法正常工作。我想念什么?

Answers:


70

由于该方法采用System.Delegate,因此需要为其指定一种特定类型的委托,并声明为此类。可以通过强制转换或通过新的DelegateType创建指定的委托来完成,如下所示:

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

另外,正如SLaks指出的那样,Dispatcher.BeginInvoke接受一个params数组,因此您可以编写:

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

或者,如果DoSomething是此对象本身的方法:

_dispatcher.BeginInvoke(new Action(this.DoSomething));

3
但是(x)=> {DoSomething(); 匹配代表的签名?我以为这就是我要指定的全部。
米卡

@Micah:System.Delegate没有签名-完全是“任何委托”。您需要为其提供一个带有sig的委托类型。符合您的用法。
Reed Copsey

@Reed但是如果代替MyMethod(Action action)(并且Action是委托),我可以调用MyMethod(()=> {DoSomething();}); 为什么我不能对BeginInvoke做同样的事情?
米卡

15
@Micah:实际上没有代表的签名,这是导致问题的原因。InvokeBeginInvoke采用一个通用Delegate对象,该对象可以表示任何签名的方法。在正常情况下(强烈将委托键入特定的签名),编译器可以推断出特定的委托类型。这就是为什么您可以在其他情况下省去委托类型的原因。但是,由于没有实际的委托类型在这里,编译器没有一个合理的基础(或者,真的,即使是手段)来使用,选择委托类型。
亚当·罗宾逊

2
@Micah:因为没有将BeginInvoke声明为BeginInvoke(Action ..),而是将BeginInvoke(System.Delegate,..)声明为它可以使用ANY委托类型,但是您必须显式指定它。
Reed Copsey

73

更短:

_dispatcher.BeginInvoke((Action)(() => DoSomething()));

8
甚至更短:我认为您不需要在表达式两边加上括号{}和分号。
sp3ctum

3
您甚至都不需要(),所以可以_dispatcher.BeginInvoke((Action)(DoSomething));
-mycroes


7

如果您从项目中引用System.Windows.Presentation.dll并添加,using System.Windows.Threading则可以访问允许使用lambda语法的扩展方法。

using System.Windows.Threading;

...

Dispatcher.BeginInvoke(() =>
{
});

我无法使它正常工作。您能否再详细一点?
Tim Pohlmann

我添加了一个简单的示例。记住要引用System.Windows.Presentation.dll
logicnet.dk

那正是我的意思,但是现在它起作用了……很奇怪。也许上次我做错了。
Tim Pohlmann

2

我们为此创建扩展方法。例如

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

现在,我们可以从以下表单中调用它:this.BeginInvoke(() => { ... })

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.