在调用 Dispatcher.Invoke 之前检查线程是否 "UI Thread" 是多余的吗?

Is checking the Thread is "UI Thread" before Calling Dispatcher.Invoke redundant?

关于

Application.Current.Dispatcher.Invoke(action);

我查看了 CheckAccess() 以及确定我是否在主线程 UI 上的各种方法。尽管在查看 InvokeDispatcher Source code 之后,它似乎调用了 CheckAccess() 并执行了其他检查

调用源代码

public void Invoke(Action callback, DispatcherPriority priority, CancellationToken cancellationToken, TimeSpan timeout)
{
   ...
   ...

   // Fast-Path: if on the same thread, and invoking at Send priority,
   // and the cancellation token is not already canceled, then just
   // call the callback directly.
   if (!cancellationToken.IsCancellationRequested && priority == DispatcherPriority.Send && CheckAccess())
   {
      SynchronizationContext oldSynchronizationContext = SynchronizationContext.Current;

      try
      {
         DispatcherSynchronizationContext newSynchronizationContext;
         if (BaseCompatibilityPreferences.GetReuseDispatcherSynchronizationContextInstance())
         {
            newSynchronizationContext = _defaultDispatcherSynchronizationContext;
         }
         else
         {
            if (BaseCompatibilityPreferences.GetFlowDispatcherSynchronizationContextPriority())
            {
               newSynchronizationContext = new DispatcherSynchronizationContext(this, priority);
            }
            else
            {
               newSynchronizationContext = new DispatcherSynchronizationContext(this, DispatcherPriority.Normal);
            }
         }
         SynchronizationContext.SetSynchronizationContext(newSynchronizationContext);

         callback();
         ...

因此,检查是否需要调用我的对话框的最可靠方法是调用 Invoke?当我无法访问 Control 时查看 CheckAccessSynchronisationContexts 解决方案似乎是多余的。

是这种情况还是我遗漏了一些边缘情况,或者我看不到隐藏的性能影响?

我想这取决于。

如果您主要追求正确性 and/or 代码简洁,那么是的,调用是多余的 - 调用

Dispatcher.Invoke(action);

在功能上等同于1

if(Dispatcher.CheckAccess())
    action();
else
    Dispatcher.Invoke(action);

但是,如果您关心的是性能,那么它就不那么明显了。 CheckAccess字面意思是

return Thread == Thread.CurrentThread;

所以即使它被调用了两倍,也几乎不会被注意到。然而,Dispatcher.Invoke 会做一些额外的工作,例如参数检查和可能的交换同步上下文,所以我猜它可能比对 CheckAccess() 的冗余调用有更大的开销。但是,与性能优化一样,没有单一的正确答案 - 这取决于您的具体情况(例如,从非 UI 线程调用此代码的可能性)。


1 显然,在调用 Dispatcher.Invoke 时,同步上下文可能会发生其他事情,但除非 action 正在利用它,结果是一样的