akj*_*shi 4 c# silverlight wpf custom-controls dispatcher
同时,通过去这个文章中,我碰到这个声明是-
如果您正在编写自己的WPF对象(例如控件),则您使用的所有方法都应在执行任何工作之前调用VerifyAccess.这可以保证您的对象仅在UI线程上使用,就像这样
//Using VerifyAccess and CheckAccess
public class MyWpfObject : DispatcherObject
{
public void DoSomething()
{
VerifyAccess();
// Do some work
}
public void DoSomethingElse()
{
if (CheckAccess())
{
// Something, only if called
// on the right thread
}
}
}
Run Code Online (Sandbox Code Playgroud)
我没有在我遇到的任何自定义控件中看到过这种情况(据我记得).
不,从来没用过这个.并且从未注意到有人在自定义控件的上下文中使用它.WPF工具包中也没有遵循此规则.
这种方法不仅会污染代码,还会使您的自定义控件负责它不应该关心的事情.考虑一直在做的情况:
// Don't do this in all methods of your custom control!
public void Foo()
{
if (!CheckAccess())
{
Dispatcher.Invoke(()=> Foo()); // Transit to UI Thread
return;
}
// .. do work in UI.
}
Run Code Online (Sandbox Code Playgroud)
乍一看这段代码看起来很好.如果您不在UI线程中,则转移到UI线程,执行操作并返回结果.对? - 错了!
问题1.当你打电话给Dispatcher.Invoke()你时,阻止调用线程直到你的请求被UI线程处理.这导致性能不佳.当然,您可以将此更改为Dispatcher.BeginInvoke()现在您的客户应该知道他们的操作是异步完成的.即如果客户端写入要控制的内容,然后立即将其读回,则无法保证该操作已由UI线程执行.
问题2.考虑Foo()从非UI线程后续调用该方法.例如,它在循环中调用:
// Somewhere not in UI
for (int i = 0; i < 1000000; i++)
{
control.Foo(); // Looks good, but performance is awful!
}
Run Code Online (Sandbox Code Playgroud)
开发人员可以在调用线程中实现一次检查,并在必要时转移到UI,而不是在线程之间无意识地跳回和值得,而不是阻塞调用线程1000000次.
此外,当您从非UI线程访问UI元素时,WPF将为您进行此检查.它的声音很大,足以粉碎应用程序,并且被做错了的开发人员听到了:).
希望这可以帮助.