在浏览this文章时,我发现了这句话 -
如果您正在编写自己的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
}
}
}
我没有在我遇到的任何自定义控件中看到过这种情况(据我记得)。
答案 0 :(得分:6)
这种方法不仅会污染代码,还会使您的自定义控件负责它不应该关心的事情。考虑一直在做的情况:
// 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.
}
乍一看这段代码看起来不错。如果您不在UI线程中,则转移到UI线程,执行操作并返回结果。对? - 错了!
问题1。当您调用Dispatcher.Invoke()
时,您会阻止调用线程,直到UI线程处理您的请求为止。这导致性能不佳。当然,您可以将此更改为Dispatcher.BeginInvoke()
,现在您的客户应该知道他们的操作是异步完成的。即如果客户端写入要控制的内容,然后立即将其读回,则无法保证该操作已由UI线程执行。
问题2。考虑从非UI线程调用方法Foo()
。例如,它在循环中调用:
// Somewhere not in UI
for (int i = 0; i < 1000000; i++)
{
control.Foo(); // Looks good, but performance is awful!
}
开发人员可以在调用线程中实现一次检查,并在必要时转移到UI,而不是在线程之间无意识地跳回去,而不是阻塞调用线程1000000次。
此外,当您从非UI线程访问UI元素时,WPF将为您进行此检查。它大声尖叫以粉碎应用程序,并被那些做错事的开发人员听到:)。
希望这有帮助。