I’m fairly new to working with threads. I was trying to set a DependencyProperty‘s value:
public States State
{
get { return (States)GetValue(StateProperty); }
set
{
Dispatcher.BeginInvoke(DispatcherPriority.Background,
//(SendOrPostCallback)delegate { SetValue(StateProperty, value); }, //works
(Action)(()=> SetValue(StateProperty, value)), //doesnt
value);
}
}
public static readonly DependencyProperty StateProperty =
DependencyProperty.Register("State", typeof(States), typeof(FTPDownload), new UIPropertyMetadata(States.Idle));
I realized the hard way that in the setter you have to use SendOrPostCallback (as it provides an argument when calling the method). it does NOT work with Action (because of the missing argument. And, wpf is really a bitch about it, debugging and finding the cause of the TargetParameterCountException with “no source available” and no clue at all.
Why do I have to use SendOrPostCallback there? and how should I know that in this case this is the right one? Because actually calling the setter works via:
Dispatcher.BeginInvoke((Action)(()=>State=States.Updating), null);
and using the SendOrPostCallback instead of course results in a TargetParameterCountException..
Just wondering if seemingly inconsistent thing like that are just common knowledge? Feeling a bit lost here, at least since googling around with SendOrPostCallback, Action and BeginInvoke as keywords had no meaningful results.
The relevant pieces of information:
1.The overload of
Dispatcher.BeginInvokethat you are using is:method: A delegate to a method that takes one argument, which is pushed onto the Dispatcher event queue.2.The
SendOrPostCallBackdelegate is declared as:3.As for
Action:Clearly, the
SendOrPostCallBackdelegate is compatible since it takes a single argument butActionis not, since it is parameterless.Of course, you can use the
Action<T>delegate, which does take a single argument, if you prefer:Alternatively, you can use a different overload of
Dispatcher.BeginInvokethat expects an argument that is of a delegate-type that takes no arguments, and get the C# compiler to do the dirty work for you in the closure:Notice that
valueis a captured variable, so please be careful.(Also, this answer doesn’t deal with any thread-safety issues, only about the delegate signatures involved.)