Делает Диспетчер.BeginInvoke помещает вызов в очередь, если он вызван из того же потока?


Если у меня есть вызов типа:

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

То, что вызывается из потока диспетчера, помещается ли он в очередь для последующего выполнения или выполняется мгновенно, поскольку ему не нужно переходить из одного потока в другой?

Спасибо,

3 2

3 ответа:

Он становится в очередь для выполнения после выполнения вашего кода в потоке диспетчера и завершения выполнения всех других очередей BeginInvoke

Стоит ли он в очереди на выполнение позже или выполняется мгновенно как это не нужно менять с одной нити на другую?

Все еще стоит в очереди. Нет никакой проверки того, из какого контекста был вызван метод. Вы можете увидеть его в источнике :

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.
}

Как указывали другие, он действительно становится в очередь да. Полезный способ обойти это-определить:

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

Который можно назвать так:

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