在调用Dispatcher.Invoke冗余之前检查Thread是否为“UI Thread”?

时间:2018-01-23 05:59:28

标签: wpf dispatcher ui-thread

关于

Application.Current.Dispatcher.Invoke(action);

我查看了CheckAccess()以及确定我是否在主UI线程上的各种方法。虽然在查看Invoke 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

因此,检查是否需要调用对话框的最可靠方法是调用CheckAccess?当我无法访问SynchronisationContexts似乎是多余的时,查看Controlreturn query.OrderByDescending(c=> c.Time.Ticks) 解决方案。

是这种情况还是有些边缘情况我不见了,或隐藏的性能打击我看不到?

1 个答案:

答案 0 :(得分:2)

我想这取决于。

如果您主要是在正确性和/或代码简洁之后,那么是,呼叫是多余的 - 调用

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 正在使用它的结果将是相同的