In regards to
Application.Current.Dispatcher.Invoke(action);
I have looked at CheckAccess()
and various ways of determining whether i'm on the main UI thread. Though after looking at the Dispatcher Source code for Invoke
, it seems to call CheckAccess()
and performs other checks anyway
Invoke Source Code
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();
...
So the most reliable way to check whether my dialog needs to be invoked is by calling Invoke
? looking at CheckAccess
and SynchronisationContexts
solutions when i dont have access to a Control
seem to be redundant.
Is this the case or is there some edge cases i'm missing, or hidden performance hit i cant see?
I guess it depends.
If you're mainly after correctness and/or code brevity, then yes, the call is redundant - calling
Dispatcher.Invoke(action);
will be functionally equivalent1 to
if(Dispatcher.CheckAccess())
action();
else
Dispatcher.Invoke(action);
If however your concern is performance, then it's not so obvious. CheckAccess
literally reads
return Thread == Thread.CurrentThread;
so even if it's called twice as many times, it will hardly be noticeable. Dispatcher.Invoke
however does some additional work, such as argument checking and, possibly, swapping synchronization context, so I guess it potentially has larger overhead than a redundant call to CheckAccess()
. But, as usual with performance optimization, there's no single right answer - it depends on your particular case (for example on the likelihood of this code being called from non-UI thread).
1 Obviously there may be additional things happening with the synchronization context when calling Dispatcher.Invoke
, but unless action
is making use of it, the result will be the same