【问题标题】:Dispatcher.BeginInvoke: Cannot convert lambda to System.DelegateDispatcher.BeginInvoke:无法将 lambda 转换为 System.Delegate
【发布时间】:2011-06-23 14:45:49
【问题描述】:

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

BeginInvoke(Delegate method, params object[] args)

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

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

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

无法将 lambda 转换为 System.Delegate。

委托的签名接受一个对象作为参数并返回void。我的 lambda 与此匹配,但它不起作用。我错过了什么?

【问题讨论】:

标签: c# wpf lambda dispatcher begininvoke


【解决方案1】:

更短:

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

【讨论】:

  • 更短:我认为你不需要大括号 {} 和表达式周围的分号。
  • 你甚至不需要(),所以它可以是_dispatcher.BeginInvoke((Action)(DoSomething));
  • 甚至是_dispatcher.BeginInvoke(DoSomething);
【解决方案2】:

由于该方法采用System.Delegate,因此您需要给它一个特定类型的委托,并声明为这样。这可以通过强制转换或通过 new 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));

【讨论】:

  • 但不是 (x) => { DoSomething(); } 匹配委托人的签名?我认为这就是我应该指定的全部内容。
  • @Micah:System.Delegate 没有签名——它只是“任何代表”。您需要为它提供一个带有 sig 的委托类型。符合您的使用情况。
  • @Reed 但是如果代替 MyMethod(Action action) (并且 Action 是委托),我可以调用 MyMethod(() => { DoSomething(); });为什么我不能为 BeginInvoke 做同样的事情?
  • @Micah:实际上没有代表的签名,这就是导致问题的原因。 InvokeBeginInvoke 采用通用的 Delegate 对象,它可以表示任何签名的方法。在正常情况下(委托被强类型化为特定签名),编译器可以推断出特定的委托类型。这就是为什么您可以在其他情况下省略委托类型。但是,由于这里 没有 实际的委托类型,因此编译器没有合理的基础(或者,实际上,甚至是 手段)来选择委托类型。
  • @Micah:因为 BeginInvoke 没有声明为 BeginInvoke(Action ..),而是 BeginInvoke(System.Delegate, ..) 这允许它使用任何委托类型,但您必须指定它明确的。
【解决方案3】:

使用内联 Lambda...

Dispatcher.BeginInvoke((Action)(()=>{
  //Write Code Here
}));

【讨论】:

    【解决方案4】:

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

    using System.Windows.Threading;
    
    ...
    
    Dispatcher.BeginInvoke(() =>
    {
    });
    

    【讨论】:

    • 我无法让它工作。你能再详细一点吗?
    • 我添加了一个简单的例子。记得引用 System.Windows.Presentation.dll
    • 这正是我的想法,但现在它可以工作了......很奇怪。也许我上次做错了什么。
    【解决方案5】:

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

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

    现在我们可以在表单中调用它:this.BeginInvoke(() =&gt; { ... })

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多