我注意到,在.NET 4.5的WPF调度员已经得到了一套新的方法来分派器的线程调用上执行的东西InvokeAsync 。 之前,.NET 4.5,我们不得不调用和BeginInvoke的该处理这syncronously和异步分别。
除了命名和可用的略有不同重载,还有的之间的重大分歧BeginInvoke
和InvokeAsync
方法?
哦,我已经签,既可以await
ED:
private async Task RunStuffOnUiThread(Action action)
{
// both of these works fine
await dispatcher.BeginInvoke(action);
await dispatcher.InvokeAsync(action);
}
没有差异的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;
}
异常处理是不同的。
您可能需要检查以下内容:
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();
}
有一个在方法签名的不同:
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)
那么,一个区别我注意到的是,InvokeAsync有一个通用的重载返回的DispatcherOperation作为返回值,并接受函数求作为其代理输入参数。 因此,你可以通过检索在InvokeAsync类似于您如何等待任务的结果的类型安全方式操作的结果。
[编辑 - 两者都是相同]
Thereotically
BeginInvoke的工作在其上调度上创建和InvokeAsync工作与该调度程序相关的线程的线程。
这意味着,如果你需要处理基于调度的当前线程的财产以后,您将使用InvokeAsync别人使用的BeginInvoke。
编辑: - 但上述评论是无意义的,一旦它被创建,你不能改变调度程序的相关线索。
上面提到的答案..谢谢同意
文章来源: What's the difference between InvokeAsync and BeginInvoke for WPF Dispatcher