Does Dispatcher.BeginInvoke queues the call if it is called from the same thread?

758 views Asked by At

If I have a call like:

Application.Current.Dispatcher.BeginInvoke(() => someAction);

that is called from the Dispatcher thread does it get queued to be executed later or gets it executed instantly as it does not need to change from one thread to another one?

3

There are 3 answers

0
Denis  Yarkovoy On BEST ANSWER

It gets queued to be executed after your running code in the Dispatcher thread and all other queued BeginInvoke's finish executing

0
Yuval Itzchakov On

does it get queued to be executed later or gets it executed instantly as it does not need to change from one thread to another one?

Still gets queued. There is no checking of which context the method was called from. You can see it in the source:

private void InvokeAsyncImpl(DispatcherOperation operation,
                             CancellationToken cancellationToken)
{
    DispatcherHooks hooks = null;
    bool succeeded = false;

    // Could be a non-dispatcher thread, lock to read
    lock(_instanceLock)
    {
        if (!cancellationToken.IsCancellationRequested &&
            !_hasShutdownFinished && 
            !Environment.HasShutdownStarted)
        {
            // Add the operation to the work queue
            operation._item = _queue.Enqueue(operation.Priority, operation);

            // Make sure we will wake up to process this operation.
            succeeded = RequestProcessing();

            if (succeeded)
            {
                // Grab the hooks to use inside the lock; but we will
                // call them below, outside of the lock.
                hooks = _hooks;
            }
            else
            {
                // Dequeue the item since we failed to request
                // processing for it.  Note we will mark it aborted
                // below.
                _queue.RemoveItem(operation._item);
            }
        } 
    }

    // Rest of method, shortened for brevity.
}
0
Ricibob On

As others have pointed out it does get queued yes. A useful way to get around this is to define:

public void DispatchIfNecessary(Action action) {
    if (!Dispatcher.CheckAccess())
        Dispatcher.Invoke(action);
    else
        action.Invoke();
}

Which can be called as:

DispatchIfNecessary(() => {
    someAction...
});