19

Previously I had

Dispatcher.Invoke(new Action(() => colorManager.Update()));

to update display to WPF from another thread. Due to design, I had to alter the program, and I must pass ColorImageFrame parameter into my ColorStreamManager.Update() method.

Following this link, I modified my dispatcher to:

Dispatcher.Invoke(new Action<ColorStreamManager, ColorImageFrame>((p,v) => p.Update(v)));

It compiles fine but would not run at all. VS2010 says "Parameter count mismatch." In my ColorStreamManager.Update() method I have RaisePropertyChanged(() => Bitmap);

Could someone point out where did I go wrong?

The signature of ColorStreamManager.Update() method is the following:

 public void Update(ColorImageFrame frame);
ikel
  • 518
  • 2
  • 6
  • 27

2 Answers2

26

You don't want the action to have parameters, because the Dispatcher isn't going to know what to pass to the method. Instead what you can do is close over the variable:

ColorImageFrame someFrame = ...;
Dispatcher.Invoke(new Action(() => colorManager.Update(someFrame)));
Servy
  • 202,030
  • 26
  • 332
  • 449
3

If you call Invoke with an Action<T1, T2> delegate, you need to pass the two Action parameters to the Invoke call:

ColorStreamManager colorManager = ...
ColorImageFrame frame = ...

Dispatcher.Invoke(
    new Action<ColorStreamManager, ColorImageFrame>((p,v) => p.Update(v)),
    colorManager,
    frame);

The Invoke overload you're using here is Dispatcher.Invoke(Delegate, Object[]).

Clemens
  • 123,504
  • 12
  • 155
  • 268
  • It's both easier and cleaner syntactically to just close over the variables instead of passing them in this way. – Servy Feb 06 '13 at 21:09
  • 1
    But it doesn't work under all circumstances. Capture of the outer variables differs from explicitly passing them to Invoke. See for example [here](http://stackoverflow.com/a/271447/1136211). Moreover OP has explicitly asked for this solution. – Clemens Feb 06 '13 at 21:15
  • That's not applicable here because `Invoke` is synchronous; it won't return until after the delegate has been run, and it is never run after the method returns. Now if this was using `BeginInvoke` then there are potential issues with closure semantics if you aren't careful. Such issues can *always* be addressed by the simple creation of a new local variable to hold a copy, if needed. As for the OP requesting it, the OP is requesting how to get the object he has to the `Update` method, he never said closures couldn't be used. – Servy Feb 06 '13 at 21:17
  • It's required for C# 1.0 when there was no mechanism for closure semantics, or for people used to that method of programming (because they come from a language that doesn't have a mechanism for creating closures), or for those that just prefer it. It's never *needed*. – Servy Feb 06 '13 at 21:19
  • 2
    Ok, you're certainly right. But still the reason for the "Parameter count mismatch" error is explained here. – Clemens Feb 06 '13 at 21:20