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

Mic*_*cah 72 c# wpf lambda dispatcher begininvoke

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

BeginInvoke(Delegate method, params object[] args)
Run Code Online (Sandbox Code Playgroud)

我试图传递一个Lambda而不是创建一个Delegate.

_dispatcher.BeginInvoke((sender) => { DoSomething(); }, new object[] { this } );
Run Code Online (Sandbox Code Playgroud)

它给了我一个编译错误说我

无法将lambda转换为System.Delegate.

委托的签名将对象作为参数并返回void.我的lambda匹配这个,但它不起作用.我错过了什么?

Ree*_*sey 68

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

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

另外,正如SLaks所指出的,Dispatcher.BeginInvoke采用了一个params数组,所以你可以写:

_dispatcher.BeginInvoke(
     new Action<MyClass>((sender) => { DoSomething(); }),
     this
  );
Run Code Online (Sandbox Code Playgroud)

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

_dispatcher.BeginInvoke(new Action(this.DoSomething));
Run Code Online (Sandbox Code Playgroud)

  • @Micah:实际上*不是*代表的签名,这是导致问题的原因.`Invoke`和`BeginInvoke`采用通用的`Delegate`对象,它可以表示任何签名的方法.在正常情况下(委托人强烈键入特定签名),编译器可以推断出特定的委托类型.这就是为什么你能够在其他场景中省略委托类型的原因.但是,由于这里**没有实际的委托类型,编译器没有合理的基础(或者,实际上甚至是*表示*)来选择委托类型. (15认同)
  • 但不是(x)=> {DoSomething(); 匹配委托的签名?我认为这是我应该指定的全部内容. (3认同)
  • @Micah:因为BeginInvoke未声明为BeginInvoke(Action ..),而是BeginInvoke(System.Delegate,..)这允许它使用任何委托类型,但您必须明确指定它. (2认同)

Erw*_*yer 67

短:

_dispatcher.BeginInvoke((Action)(() => DoSomething()));
Run Code Online (Sandbox Code Playgroud)

  • 更短:我不认为你需要括号{}和分号围绕表达式. (8认同)
  • 你甚至不需要(),所以它可以是`_dispatcher.BeginInvoke((Action)(DoSomething));` (3认同)

log*_*.dk 6

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

using System.Windows.Threading;

...

Dispatcher.BeginInvoke(() =>
{
});
Run Code Online (Sandbox Code Playgroud)


Joh*_*ers 6

使用Inline Lambda ...

Dispatcher.BeginInvoke((Action)(()=>{
  //Write Code Here
}));
Run Code Online (Sandbox Code Playgroud)


Sha*_*tin 5

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

public static void BeginInvoke(this Control control, Action action)
    => control.BeginInvoke(action);
Run Code Online (Sandbox Code Playgroud)

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