Winform同步调用异步函数死锁原因分析、为什么要用异步 (6)

可以看到在Windows平台是通过IOCP触发回调事件。在Unix平台是在SocketAsyncEngine类创建while(true)循环的执行线程,再通过Wait epoll或kqueue获取IO事件,最后触发回调事件。IOPC为异步非阻塞IO、epoll为同步非阻塞IO,IOCP、epoll会涉及IO模型、IO多路复用等知识,网上介绍较多,可以自行查阅。同时需要注意AwaitableSocketAsyncEventArgs既继承SocketAsyncEventArgs类也实现IValueTaskSource接口。

HttpClient.GetStringAsync请求:

image-20211017200529706

NetworkStream.WriteAsync在Windows平台实现:

image-20211017200552834

NetworkStream.WriteAsync在Unix平台实现:

image-20211017200610472

async await推荐实践方法

async/await适用于IO型(文件读取、网络通信)、延时型任务。对于计算型任务可以使用Task.Factory创建LongRunning任务,该任务会独立新建一个后台线程进行处理。

关于MySql驱动组件: 建议采用MySqlConnector组件。因为MySqlConnector组件支持异步IO,MySql.Data组件不支持真实的异步IO。

如果条件允许、尽量使用ConfigureAwait(false)。如果不设置在Winform场景下会调用SynchronizationContext.Post通过UI线程执行回调函数,同步方法调用异步方式时会出现死锁。

Task方法替代清单:

同步方法 异步方式 描述信息
task.Wait   await task   等待一个任务执行完成  
task.Result   await task   获取任务返回结果  
Task.WaitAny   await Task.WhenAny   等待其中一个任务执行完成,继续执行  
Task.WaitAll   await Task.WhenAll   等待所有任务执行完成,继续执行  
Thread.Sleep   await Task.Delay   延时几秒继续执行  

Demo代码地址 : https://gitee.com/RiverBied/async-demo

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

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