Dispatcher.Invoke和lambda语法 - 新行动

问题描述:

什么是VSDispatcher.Invoke和lambda语法 - 新行动

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

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

之间的差异。如果编译器抱怨,我会用其他的,但我不知道到底发生了什么上。

+2

它们是相同的。第二个片段中的lambda被隐式转换为一个Action。虽然通常是相同的,但我也推荐使用TextBlock的Dispatcher,比如'txtRowCount.Dispatcher.Invoke(()=> txtRowCount.Text = string.Format(“{0}”,rowCount));' – Clemens

+0

https:/ /stackoverflow.com/questions/765966/what-is-the-difference-between-new-action-and-a-lambda – mm8

它很可能取决于您正在调用和传递委托的方法。例如,对于这样的签名的方法可以使用Lambda隐含创建Action

void RunAction(Action thing) {} 

虽然这样的方法就无法弄清楚你想要什么类型的委托:

void RunDelegate(Delegate thing) {} 

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

在另一方面,Action是没有参数和不返回值的方法的具体代表:

delegate void Action(); 

所以,当一个方法有一个类型为Action参数,那么任何拉姆达签名符合该代表可以隐式转换为您。


对于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; 
}