Подтвердить что ты не робот

Какая разница между InvokeAsync и BeginInvoke для диспетчера WPF

В .NET 4.5 я заметил, что WPF Dispatcher получил новый набор методов для выполнения файлов в потоке Диспетчера, называемом InvokeAsync. Раньше .NET 4.5 у нас Invoke и BeginInvoke которые обрабатывали это синхронно и асинхронно соответственно.

Помимо названий и немного разных перегрузок, существуют ли какие-либо существенные различия между методами BeginInvoke и InvokeAsync?

О, и я уже проверил, оба могут быть await ed:

private async Task RunStuffOnUiThread(Action action)
{
    // both of these works fine
    await dispatcher.BeginInvoke(action);
    await dispatcher.InvokeAsync(action);
}
4b9b3361

Ответ 1

Нет различий, поскольку метод BeginInvoke вызывает частный LegacyBeginInvokeImpl метод, который itslef вызывает частный метод InvokeAsyncImpl (метод, используемый InvokeAsync). Так что это в основном то же самое. Кажется, это простой рефакторинг, однако странно, что методы BeginInvoke не были отмечены как устаревшие.

BeginInvoke:

public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method)
{
    return this.LegacyBeginInvokeImpl(priority, method, null, 0);
}

private DispatcherOperation LegacyBeginInvokeImpl(DispatcherPriority priority, Delegate method, object args, int numArgs)
{
    Dispatcher.ValidatePriority(priority, "priority");
    if (method == null)
    {
        throw new ArgumentNullException("method");
    }
    DispatcherOperation dispatcherOperation = new DispatcherOperation(this, method, priority, args, numArgs);
    this.InvokeAsyncImpl(dispatcherOperation, CancellationToken.None);
    return dispatcherOperation;
}

InvokeAsync:

public DispatcherOperation InvokeAsync(Action callback, DispatcherPriority priority)
{
    return this.InvokeAsync(callback, priority, CancellationToken.None);
}

public DispatcherOperation InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
    if (callback == null)
    {
        throw new ArgumentNullException("callback");
    }
    Dispatcher.ValidatePriority(priority, "priority");
    DispatcherOperation dispatcherOperation = new DispatcherOperation(this, priority, callback);
    this.InvokeAsyncImpl(dispatcherOperation, cancellationToken);
    return dispatcherOperation;
}

Ответ 2

Существует различие в сигнатуре метода:

BeginInvoke(Delegate, Object[])
InvokeAsync(Action)

Для BeginInvoke() компилятор создает массив Object[] неявно, а для InvokeAsync() такой массив не нужен:

IL_0001:  ldarg.0
IL_0002:  call       instance class [WindowsBase]System.Windows.Threading.Dispatcher [WindowsBase]System.Windows.Threading.DispatcherObject::get_Dispatcher()
IL_0007:  ldarg.1
IL_0008:  ldc.i4.0
IL_0009:  newarr     [mscorlib]System.Object
IL_000e:  callvirt   instance class [WindowsBase]System.Windows.Threading.DispatcherOperation [WindowsBase]System.Windows.Threading.Dispatcher::BeginInvoke(class [mscorlib]System.Delegate, object[])


IL_0014:  ldarg.0
IL_0015:  call       instance class [WindowsBase]System.Windows.Threading.Dispatcher [WindowsBase]System.Windows.Threading.DispatcherObject::get_Dispatcher()
IL_001a:  ldarg.1
IL_001b:  callvirt   instance class [WindowsBase]System.Windows.Threading.DispatcherOperation [WindowsBase]System.Windows.Threading.Dispatcher::InvokeAsync(class [mscorlib]System.Action)

Ответ 3

[Изменить - оба одинаковы]

Thereotically

BeginInvoke работает над потоком, на котором был создан диспетчер, и InvokeAsync работает с потоком, с которым связан диспетчер.

Это означает, что если вам нужно обработать somthing на основе текущего потока диспетчера, вы будете использовать InvokeAsync else, используя BeginInvoke.

EDIT: - но выше комментарий не имеет смысла, поскольку вы не можете изменить связанный поток диспетчера после его создания.

Согласитесь с выше упоминанием ответ.. спасибо