异步函数async await在wpf都做了什么? (2)

这里还有一个小提示,不管async函数里面有没有await,都会生成状态机,只是MoveNext函数执行同步方法,因此没await的情况下避免将函数标记为async,会损耗性能

同样的这里貌似没能获取到原因,但是有个很关键的地方,就是Create函数为啥要获取当前同步执行上下文,之后我从MSDN找到关于SynchronizationContext
的介绍,有兴趣的朋友可以去阅读以下,以下是各个.NET框架使用的SynchronizationContext:

SynchronizationContext 默认
WindowsFormsSynchronizationContext   WindowsForm  
DispatcherSynchronizationContext   WPF/Silverlight  
AspNetSynchronizationContext   ASP.NET  

我们貌似已经一步步接近真相了,接下来我们来看看DispatcherSynchronizationContext

二.DispatcherSynchronizationContext

首先来看看DispatcherSynchronizationContext类的比较关键的几个函数实现:

public DispatcherSynchronizationContext(Dispatcher dispatcher, DispatcherPriority priority) { if (dispatcher == null) { throw new ArgumentNullException("dispatcher"); } Dispatcher.ValidatePriority(priority, "priority"); _dispatcher = dispatcher; _priority = priority; SetWaitNotificationRequired(); } //同步执行 public override void Send(SendOrPostCallback d, object state) { if (BaseCompatibilityPreferences.GetInlineDispatcherSynchronizationContextSend() && _dispatcher.CheckAccess()) { _dispatcher.Invoke(DispatcherPriority.Send, d, state); } else { _dispatcher.Invoke(_priority, d, state); } } //异步执行 public override void Post(SendOrPostCallback d, object state) { _dispatcher.BeginInvoke(_priority, d, state); }

我们貌似看到了熟悉的东西了,Send函数调用Dispatcher的Invoke函数,Post函数调用Dispatcher的BeginInvoke函数,那么是否WPF执行异步函数之后会调用这里的函数吗?我用dnspy进行了调试:

异步函数async await在wpf都做了什么?

我通过调试之后发现,当等待执行完整个状态机的之后,也就是两秒后跳转到该Post函数,那么,我们可以将之前的WPF那段代码大概可以改写成如此:

private async void Async_Click(object sender, RoutedEventArgs e) { //async生成状态机的Create函数。获取到UI主线程的同步执行上下文 DispatcherSynchronizationContext synchronizationContext = (DispatcherSynchronizationContext)SynchronizationContext.Current; //UI主线程执行 Debug.WriteLine($"Thread Id is Thread:{Thread.CurrentThread.ManagedThreadId},Is Thread Pool:{Thread.CurrentThread.IsThreadPoolThread}"); //开始在状态机的MoveNext执行该异步操作 var result= await ExampleTask(2); //等待两秒,异步执行完成,再在同步上下文异步执行 synchronizationContext.Post((state) => { //模仿_dispatcher.BeginInvoke Debug.WriteLine($"Thread Id is Thread:{Thread.CurrentThread.ManagedThreadId},Is Thread Pool:{Thread.CurrentThread.IsThreadPoolThread}"); Debug.WriteLine(result); Debug.WriteLine("Async Completed"); },"Post"); }

输出结果:

Thread Id is Thread:1,Is Thread Pool:False Thread Id is Thread:1,Is Thread Pool:False It's Async Completed in 2 seconds Async Completed

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjgpd.html