2

我对使用线程还很陌生。我试图设置 aDependencyProperty的值:

    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));

我意识到在设置器中你必须使用 SendOrPostCallback 的艰难方式(因为它在调用方法时提供了一个参数)。它不适用于 Action (因为缺少参数。而且,wpf 真的是个婊子,调试并找到 TargetParameterCountException 的原因,“没有可用的源”并且根本没有任何线索。

为什么我必须在那里使用 SendOrPostCallback?我怎么知道在这种情况下这是正确的?因为实际上调用 setter 是通过以下方式工作的:

Dispatcher.BeginInvoke((Action)(()=>State=States.Updating), null);

并使用 SendOrPostCallback 而不是当然会导致 TargetParameterCountException..

只是想知道这样看似不一致的事情是否只是常识?在这里感觉有点迷失,至少因为使用 SendOrPostCallback、Action 和 BeginInvoke 作为关键字进行谷歌搜索并没有有意义的结果。

4

1 回答 1

7

相关资料:

1.您正在使用的重载Dispatcher.BeginInvoke是:

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

method: 一个方法的委托,该方法接受一个参数,该参数被推送到 Dispatcher 事件队列。

2.SendOrPostCallBack委托声明为:

public delegate void SendOrPostCallback(object state)

3.至于Action

public delegate void Action()

显然,SendOrPostCallBack委托是兼容的,因为它接受单个参数,但Action不是,因为它是无参数的。

当然,如果您愿意,您可以使用Action<T>委托,它接受一个参数:

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

或者,您可以使用不同的重载Dispatcher.BeginInvoke它需要一个不带参数的委托类型的参数,并让 C# 编译器在闭包中为您完成脏活:

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

请注意,这value是一个捕获的变量,所以请小心。

(此外,此答案不涉及任何线程安全问题,仅涉及所涉及的委托签名。)

于 2010-11-30T15:31:23.567 回答