无法将匿名方法转换为类型“System.Delegate”,因为它不是委托类型。

15

我想在WPF应用程序的主线程上执行此代码,但是遇到了错误,我无法弄清楚问题所在:

private void AddLog(string logItem)
        {

            this.Dispatcher.BeginInvoke(
                delegate()
                    {
                        this.Log.Add(new KeyValuePair<string, string>(DateTime.Now.ToLongTimeString(), logItem));

                    });
        }

1
请看这里:https://dev59.com/92445IYBdhLWcg3wTIZf - MethodMan
2个回答

25

匿名函数(lambda表达式和匿名方法)必须转换为一个特定的委托类型,而Dispatcher.BeginInvoke只需要Delegate。有两个选项...

  1. 仍然使用现有的BeginInvoke调用,但指定委托类型。这里有各种方法,但我通常将匿名函数提取到前面的语句中:

    Action action = delegate() { 
         this.Log.Add(...);
    };
    Dispatcher.BeginInvoke(action);
    
  2. Dispatcher上编写一个扩展方法,该方法接受Action而不是Delegate

  3. public static void BeginInvokeAction(this Dispatcher dispatcher,
                                         Action action) 
    {
        Dispatcher.BeginInvoke(action);
    }
    

    然后,您可以使用隐式转换调用扩展方法。

    this.Dispatcher.BeginInvokeAction(
            delegate()
            {
                this.Log.Add(...);
            });
    

    总的来说,我建议您使用lambda表达式而不是匿名方法:

Dispatcher.BeginInvokeAction(() => this.Log.Add(...));

编辑:如评论中所述,Dispatcher.BeginInvoke在.NET 4.5中增加了一个重载,直接接受一个Action参数,因此在这种情况下您不需要使用扩展方法。


我曾经遇到过同样的问题,后来发现在.NET 4.5版本中,Dispatcher类得到了重载(例如:http://msdn.microsoft.com/en-us/library/hh199416(v=vs.110).aspx),可以接受Action委托,因此代码可以在不需要显式指定委托类型的情况下工作。 - Mark Vincze

4
您还可以使用MethodInvoker来实现此功能:
private void AddLog(string logItem)
        {
            this.Dispatcher.BeginInvoke((MethodInvoker) delegate
            {
                this.Log.Add(new KeyValuePair<string, string>(DateTime.Now.ToLongTimeString(), logItem));
            });
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接