具有匿名委托的Dispatcher.Invoke适用于Silverlight但不适用于WPF

时间:2010-07-19 19:56:42

标签: c# wpf asynchronous begininvoke anonymous-delegates

在Silverlight 4中,我有一个自定义服务类,它有一个异步的Completed事件。在Completed事件中,我获取返回的数据并通过以下方式调用populate方法:

private void service_Completed(object sender, CompletedEventArgs args)
{
    Dispatcher.BeginInvoke(() => populateInbox(args.Jobs));
}

private void populateInbox(List<JobViewModel> jobs)
{
    inbox.DataContext = jobs;
}

BeginInvoke在SL4中有效,但是当我将其移植到WPF时,我收到以下错误:

  

无法将lambda表达式转换为'System.Delegate'类型,因为它不是委托类型

我尝试将其更改为内联,匿名,参与代表:

Dispatcher.BeginInvoke(delegate(List<JobViewModel> jobs)
{
    inbox.DataContext = jobs;
});

但是,这会产生相同的编译时错误。

知道如何让它在WPF中运行吗?重构使用BackgroundWorker对我来说不是一个选择。

2 个答案:

答案 0 :(得分:26)

您需要指定显式委托类型。只需使用Action

Dispatcher.BeginInvoke(new Action(() => populateInbox(args.Jobs));

但是,您可以避免像这样关闭args.Jobs值:

Dispatcher.BeginInvoke(new Action((jobs) => populateInbox(jobs)), jobs);

这是因为Dispatcher.BeginInvoke的单参数版本在Silverlight中的签名与WPF中的签名不同。在Silverlight中,它需要Action,这允许C#编译器隐式地将您的lambda键入Action。在WPF中,它需要Delegate(类似于Winforms中的Control.BeginInvoke模拟),因此C#编译器必须明确指定委托类型。

答案 1 :(得分:2)

在WPF和winforms中,你必须先将它转换为MethodInvoker,否则你将得到错误无法将匿名方法转换为类型'System.Delegate',因为它不是委托类型。

Dispatcher.BeginInvoke((MethodInvoker) delegate(List<JobViewModel> jobs)
{
   inbox.DataContext = jobs;
});

了解更多信息:http://msdn.microsoft.com/en-us/library/system.windows.forms.methodinvoker.aspx