正确使用(或不使用)Dispatcher.CheckAccess()

Dal*_*tan 14 c# wpf

在Winforms中,所有控件都有一个InvokeRequired属性,如果必须调用则返回true.[Begin]调用控件以修改它.

在WPF中,在DispatcherObject.CheckAccess()and中有一个看似相似的结构Dispatcher.CheckAccess(),但我对该EditorBrowsable(EditorBrowsableState.Never)属性感到害怕.当我禁用这样的编辑器浏览时,我用它来表示"你应该这样做.不,真的.如果需要解决你的问题,你就错误地设计了解决你的首要问题的解决方案." 另一方面,我发现的唯一替代方案(事实上,我的原始解决方案)是Thread.CurrentThread.ManagedThreadId == 1.(这太可怕了.它在通用情况下不起作用.我知道.但它确实适用于我的有限用途.)

MSDN 文档上的存在和推理背后沉默的EditorBrowsable属性.它确实意味着"不要使用它",因为如果我输入它,或者它有其他一些不那么禁止的含义吗?

Dan*_*zey 20

在WPF中,Dispatcher.Invoke无论当前线程如何,都可以调用它,并且它将相应地处理调用 - 如果您已经在正确的线程上,它将只调用您的代码,并且它用于CheckAccess处理此行为.

对于BeginInvoke当前使用的线程无关紧要:BeginInvoke始终是异步的,执行顺序取决于您添加到调度程序队列的项目的优先级.

如果您根本不应该使用该方法,则它不会是公共的:该属性的意图仅在于将成员隐藏在诸如Intellisense和其他编辑器浏览器之类的机制中.你通常不需要Dispatcher.CheckAccess()自己使用,这可能是为什么它被标记为不可浏览,但这是我们只能猜测的智慧(除非Eric Lippert正在观看;-)

总结:只需打电话Dispatcher.Invoke,不要担心CheckAccess.

  • 我认为检查线程访问权以确定使用哪个是有好处的.在某些情况下,基于CheckAccess进行显式控制或执行特定的先决条件是有意义的.但养成它的习惯是不好的,因为它只是重复努力.坦率地说,Dispatcher.cs是我见过的最乱的.NET类之一. (2认同)
  • Dan,当您说“...如果您已经在正确的线程上,它只会调用您的代码,并且它使用 CheckAccess 来处理此行为”时,我不确定您是否正确。如果您查看 Dispatcher 类的源代码,似乎只有在 DispatcherPriority 为 Send 时才会调用 CheckAccess。IMO,为您的 Dispatcher 创建一个包装类是一个好主意,这对于单元测试很有用,但是您可以非常轻松地为每个 Invoke 调用添加 CheckAccess。过去从主线程调用 Dispatcher.Invoke 给我带来了一些问题。 (2认同)