WPF Dispatcher的InvokeAsync和BeginInvoke之间有什么区别

时间:2012-11-16 08:08:52

标签: c# wpf .net-4.5 async-await

我在.NET 4.5中注意到WPF Dispatcher已经获得了一组新方法来在Dispatcher的线程上执行名为InvokeAsync的线程。以前,.NET 4.5我们有InvokeBeginInvoke分别同步和异步处理这个。

除了可用的命名和稍微不同的重载外,BeginInvokeInvokeAsync方法之间是否存在重大差异?

哦,我已经检查过,两者都可以await编辑:

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

5 个答案:

答案 0 :(得分:42)

由于BeginInvoke方法调用私有方法LegacyBeginInvokeImplInvokeAsyncImpl使用的方法)的私有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;
}

答案 1 :(得分:16)

异常处理方式不同。

您可能需要查看以下内容:

private async void OnClick(object sender, RoutedEventArgs e)
{
    Dispatcher.UnhandledException += OnUnhandledException;
    try
    {
        await Dispatcher.BeginInvoke((Action)(Throw));
    }
    catch
    {
        // The exception is not handled here but in the unhandled exception handler.
        MessageBox.Show("Catched BeginInvoke.");
    }

    try
    {
       await Dispatcher.InvokeAsync((Action)Throw);
    }
    catch
    {
        MessageBox.Show("Catched InvokeAsync.");
    }
}

private void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
    MessageBox.Show("Catched UnhandledException");
}

private void Throw()
{
    throw new Exception();
}

答案 2 :(得分:12)

方法签名有所不同:

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 :(得分:1)

嗯,我注意到的一个区别是InvokeAsync具有泛型重载,该重载返回DispatcherOperation作为返回值,并接受Func作为其委托输入参数。因此,您可以通过InvokeAsync以类型安全的方式检索操作的结果,类似于等待任务结果的方式。

答案 4 :(得分:-2)

[编辑 - 两者都相同]

Thereotically

BeginInvoke适用于创建了调度程序的线程,InvokeAsync适用于与调度程序关联的线程。

这意味着如果你需要根据调度程序的当前线程处理somthing,你将使用InvokeAsync,否则使用BeginInvoke。

编辑: - 但是上面的评论没有意义,因为一旦创建了调度程序,就无法更改它的关联线程。

同意以上提及答案..谢谢