什么是对WPF调度InvokeAsync而BeginInvoke的区别(What's the

2019-07-03 21:07发布

我注意到,在.NET 4.5的WPF调度员已经得到了一套新的方法来分派器的线程调用上执行的东西InvokeAsync 。 之前,.NET 4.5,我们不得不调用和BeginInvoke的该处理这syncronously和异步分别。

除了命名和可用的略有不同重载,还有的之间的重大分歧BeginInvokeInvokeAsync方法?

哦,我已经签,既可以await ED:

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

Answer 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;
}


Answer 2:

异常处理是不同的。

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

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();
}


Answer 3:

有一个在方法签名的不同:

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)


Answer 4:

那么,一个区别我注意到的是,InvokeAsync有一个通用的重载返回的DispatcherOperation作为返回值,并接受函数求作为其代理输入参数。 因此,你可以通过检索在InvokeAsync类似于您如何等待任务的结果的类型安全方式操作的结果。



Answer 5:

[编辑 - 两者都是相同]

Thereotically

BeginInvoke的工作在其上调度上创建和InvokeAsync工作与该调度程序相关的线程的线程。

这意味着,如果你需要处理基于调度的当前线程的财产以后,您将使用InvokeAsync别人使用的BeginInvoke。

编辑: - 但上述评论是无意义的,一旦它被创建,你不能改变调度程序的相关线索。

上面提到的答案..谢谢同意



文章来源: What's the difference between InvokeAsync and BeginInvoke for WPF Dispatcher