异步I/O方法是如何处理的
本文关键字:处理 何处理 方法 异步 | 更新日期: 2023-09-27 18:16:47
在阅读了大量关于async-await的内容后,我只能找到在GUI线程(WPF/WinForms)中使用它的好处。
在什么情况下它会减少WCF服务中线程的创建?程序员是否必须通过选择在web服务中实现async-await来对服务中的每个方法使用async-await ?在充满异步等待的服务中使用一些非异步等待方法会降低服务的效率吗?如何?
最后一个问题-有人说使用'await Task.Run(()=>…)'不是一个"真正的async-await"。他们这么说是什么意思?
提前感谢,Stav .
编辑:这两个答案都很好,但要想更深入地解释async-await是如何工作的,我建议阅读@Stephen Cleary的回答:https://stackoverflow.com/a/7663734/806963
要理解他的回答需要以下主题:SynchronizationContext、SynchronizationContext.Current TaskScheduler、TaskScheduler.Current Threadpool。
在服务器应用程序(如WCF)中async/await的真正好处是异步I/o。
当你调用一个同步I/O方法时,调用线程将被阻塞,等待I/O完成。这个线程不能被其他请求使用,它只能等待结果。当更多的请求到达时,线程池将创建更多的线程来处理它们,浪费了大量的资源-内存,当等待的线程被打开时上下文切换…
如果你使用异步IO,线程不会被阻塞。在启动异步IO操作之后,线程池再次可以使用它。当异步操作完成后,线程池分配一个线程来继续处理请求。没有资源浪费。
来自MSDN(它是关于文件I/O,但也适用于其他)
在同步文件I/O中,线程开始一个I/O操作,并立即进入等待状态,直到I/O请求完成。执行异步文件I/O的线程通过调用适当的函数向内核发送I/O请求。如果请求被内核接受,调用线程继续处理另一个作业,直到内核向线程发出I/O操作完成的信号。然后,它中断当前的作业,并根据需要处理来自I/O操作的数据。
现在您可能可以看到为什么如果任务中的IO是同步完成的,await Task.Run()
不会提供任何好处。一个线程无论如何都会被阻塞,只是不是调用Task.Run()
的线程。
您不需要异步实现每个方法来查看性能的改进(尽管始终异步执行I/O应该成为一种习惯)。
在什么情况下它会减少WCF服务中线程的创建?
如果你有一个动作将等待IO操作(从数据库读取,调用外部web服务,…),使用async/await释放正在处理WCF请求的托管线程。这使得线程可用于其他请求,等待IO的完成。它可以更有效地使用线程池。
在阅读了大量关于async-await的内容后,我只能找到在GUI线程中使用它的好处
对于客户机应用程序,这是我所知道的关键好处,因为与服务器应用程序相比,托管线程耗尽的可能性要小得多。
有人说使用'await Task.Run(()=>…)'不是"真正的async-await"。
你分配了一个新的托管线程来运行你的新任务,所以你没有保存任何托管线程。