difference between SendOrPostCallback and Action in multithreaded environment?

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.

Answers


The relevant pieces of information:

1.The overload of Dispatcher.BeginInvoke that you are using is:

public DispatcherOperation BeginInvoke(
    DispatcherPriority priority,
    Delegate method,
    Object arg
)

method: A delegate to a method that takes one argument, which is pushed onto the Dispatcher event queue.

2.The SendOrPostCallBack delegate is declared as:

public delegate void SendOrPostCallback(object state)

3.As for Action:

public delegate void Action()

Clearly, the SendOrPostCallBack delegate is compatible since it takes a single argument but Action is not, since it is parameterless.

Of course, you can use the Action<T> delegate, which does take a single argument, if you prefer:

Dispatcher.BeginInvoke(DispatcherPriority.Background,
                        new Action<States>(arg => SetValue(StateProperty, arg)),
                        value);

Alternatively, you can use a different overload of Dispatcher.BeginInvoke that 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:

Dispatcher.BeginInvoke(DispatcherPriority.Background,
                        new Action(() => SetValue(StateProperty, value));

Notice that value is a captured variable, so please be careful.

(Also, this answer doesn't deal with any thread-safety issues, only about the delegate signatures involved.)


Need Your Help

rails new and rails -v throwing this error

ruby-on-rails

This is what happened when I ran rails -v or rails new. Haven't mucked around at all either. I figured i'd post here before trashing the install and re-installing rails.

iis apps & subapps, interaction of web.config

asp.net web-config routes

We've got a web server which has been running a number of separate applications within the same site with no problem. I just added a new application at the root. Many of these applications use rout...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.