多线程环境下SendOrPostCallback和Action的区别?
我对使用线程还很陌生。我试图设置 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 作为关键字进行谷歌搜索没有有意义的结果。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
相关信息:
1.
Dispatcher 的重载。您正在使用的 BeginInvoke
是:method
:一个方法的委托需要一个参数,该方法被推送到调度程序事件队列。2.
SendOrPostCallBack
< /strong> 委托声明为:3.As for < strong>
Action
:显然,
SendOrPostCallBack
委托是兼容的,因为它采用单个参数,但Action
则不然,因为它是无参数的。当然,您可以使用
Action
委托,如果您愿意,它确实采用单个参数:
或者,您可以使用 Dispatcher.BeginInvoke 的不同重载,它需要一个采用委托类型的参数没有参数,并让 C# 编译器在闭包中为您完成脏活:
请注意,
value
是捕获的变量,因此请小心。(此外,这个答案不处理任何线程安全问题,仅涉及所涉及的委托签名。)
The relevant pieces of information:
1.The overload of
Dispatcher.BeginInvoke
that you are using is: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:3.As for
Action
:Clearly, the
SendOrPostCallBack
delegate is compatible since it takes a single argument butAction
is 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.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: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.)