Dispatcher.Invoke和lambda语法 - 新动作

时间:2017-09-15 08:38:17

标签: wpf lambda delegates

之间的区别是什么
Application.Current.Dispatcher.Invoke(
    new Action(() =>
    {
        txtRowCount.Text = string.Format("{0}", rowCount);
    })
); //end-Invoke

VS

Application.Current.Dispatcher.Invoke(
    () =>
    {
        txtRowCount.Text = string.Format("{0}", rowCount);
    }
); //end-Invoke

如果编译器抱怨,我将使用另一个,但我不知道它到底发生了什么。

1 个答案:

答案 0 :(得分:1)

它很可能取决于您调用哪种方法并将委托传递给。例如,具有此类签名的方法可以使用lambda隐式创建Action

void RunAction(Action thing) {}

虽然这样的方法无法确定您想要的委托类型:

void RunDelegate(Delegate thing) {}

原因是Delegate类型是可以表示任何delegate表达式的基类。例如,您可以传递第二个函数ActionFunc<T>Predicate<T>EventHandler或您能想到的任何其他代理,包括自定义代理。在这种情况下,编译器/运行时不知道将自定义委托转换为什么。函数的责任是要么弄清楚如何调用委托,要么在不理解它的情况下抛出异常。

另一方面,Action是没有参数且不返回值的方法的特定委托:

delegate void Action();

因此,当方法的参数类型为Action时,可以为您隐式转换任何符合该委托的签名的lambda。

对于Dispatcher.BeginInvoke方法,它接受Delegate,你可以传递任何带0参数的委托(如果它返回一些东西就没问题,但我怀疑返回值是否用于任何东西) )。因此,您可以传递类似ActionFunc<T>的内容。如果你传递一个委托,它要求传递给它的参数,它仍然会编译,但是当Dispatcher尝试调用该方法时会在运行时抛出异常。

为了演示,我制作了一个快速的小控制台应用程序。

static int Main(string[] args)
{
    // These work
    Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => Console.WriteLine("Action")));
    Dispatcher.CurrentDispatcher.BeginInvoke(new Func<int>(() => { Console.WriteLine("Func<int>"); return 42; }));

    // This one throws a TargetParameterCountException when the dispatcher gets to it
    //Dispatcher.CurrentDispatcher.BeginInvoke(new Action<bool>(b => Console.WriteLine("Action<bool>")));

    // Queue a dispatcher shutdown at the end and run the dispatcher
    Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => Dispatcher.CurrentDispatcher.InvokeShutdown()));
    Dispatcher.Run();

    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
    return 0;
}