Dispatcher.Invoke with anonymous delegate works in Silverlight but not WPF
Asked Answered
E

2

10

In Silverlight 4 I have a custom service class which has an asynchronous Completed event. Inside the Completed event I take the returned data and invoke a populate method via something like this:

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

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

The BeginInvoke works in SL4, however when I ported it to WPF I get the following error:

Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type

I tried changing it to an in-line, anonymous, paramaterized delegate:

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

However, that yields the same compile-time error.

Any idea how to get this to work in WPF? Refactoring to use the BackgroundWorker is not an option for me.

England answered 19/7, 2010 at 19:56 Comment(1)
Why is "Dispatcher.Invoke" in the title and in the real question you ask about "Dispatcher.BeginInvoke"? It's not the same...Visitor
H
26

You need to specify an explicit delegate type. Just use an Action.

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

You could, however, avoid having to close over the args.Jobs value like this:

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

This is because the single-parameter version of Dispatcher.BeginInvoke has a different signature in Silverlight than in WPF. In Silverlight, it takes an Action, which allows the C# compiler to implicitly type your lambda as an Action. In WPF, it takes a Delegate (like its Control.BeginInvoke analog in Winforms), so the C# compiler has to have a delegate type explicitly specified.

Householder answered 19/7, 2010 at 19:59 Comment(4)
I'm getting this error now: An object reference is required for the non-static field, method, or property 'System.Windows.Threading.Dispatcher.BeginInvoke(System.Delegate, params object[])'. I separated it out into 2 lines to try and see what is causing the error. var d = new Action(() => populateInbox(args.Jobs)); Dispatcher.BeginInvoke(d, args.Jobs); Error happens on the 2nd line.England
Dispatcher.BeginInvoke(d, new object[] { args.Jobs }); Does not work either.England
@Edward: Dispatcher is not a static class. You'll have to call this function either within the context of a UI element that has a Dispatcher property, or you'll have to pass in the dispatcher as another argument.Householder
Yeah, you're right. I'm trying to use a WPF user control from within an Excel workbook project. The WPF user control is hosted in an ActionPane with an ElementHost. The pane is instantiated in a Ribbon control which does not have a Dispatcher property. Thanks.England
C
2

In WPF and winforms you must cast it to a MethodInvoker first, otherwise you will get the error Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type.

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

For more info: http://msdn.microsoft.com/en-us/library/system.windows.forms.methodinvoker.aspx

Cankerous answered 15/4, 2011 at 21:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.