我很擅长使用线程。我试图设置DependencyProperty
的值:
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));
我意识到在setter中你必须使用SendOrPostCallback(因为它在调用方法时提供了一个参数)。它不适用于Action(因为缺少参数。而且,wpf实际上是一个关于它的婊子,调试并找到TargetParameterCountException的原因,“没有可用的源”并且根本没有任何线索。
为什么我必须在那里使用SendOrPostCallback?我怎么知道在这种情况下这是正确的?因为实际上通过以下方式调用setter:
Dispatcher.BeginInvoke((Action)(()=>State=States.Updating), null);
并使用SendOrPostCallback而不是导致TargetParameterCountException ..
只是想知道看似不一致的事情是否只是常识?感觉有点迷失在这里,至少自从谷歌搜索SendOrPostCallback,Action和BeginInvoke作为关键字没有有意义的结果。
答案 0 :(得分: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);
或者,你可以使用different overload Dispatcher.BeginInvoke
期望一个带有 no 参数的委托类型的参数,并让C#编译器去做关闭时你的肮脏工作:
Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() => SetValue(StateProperty, value));
请注意value
是一个捕获的变量,所以请小心。
(另外,这个答案不涉及任何线程安全问题,只涉及涉及的代理签名。)