如何处理异步I / O方法

时间:2015-10-08 23:03:51

标签: c# .net asynchronous async-await clr

在阅读了很多关于async-await之后,我只能在GUI线程(WPF / WinForms)中找到使用它的好处。

在什么情况下它会减少WCF服务中线程的创建? 程序员是否必须通过选择在Web服务中实现async-await,在服务中的每个方法上使用async-await ?在一个充满async-await的服务中制作一些非异步等待方法会降低我的服务效率吗?怎么样?

最后一个问题 - 有人说使用'等待Task.Run(()=> ...)'不是"真正的异步 - 等待"。他们这么说是什么意思?

感谢advence, STAV。

修改

这两个答案都很出色但是对于asper-await如何工作的偶数解释,我建议在这里阅读@Stephen Cleary的回答: https://stackoverflow.com/a/7663734/806963

理解他的答案需要以下主题: 的SynchronizationContext,SynchronizationContext.Current,的TaskScheduler,TaskScheduler.Current,线程池。

2 个答案:

答案 0 :(得分:4)

服务器应用程序(如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操作的数据。

现在您可能已经知道为什么await Task.Run()如果任务中的IO同步完成将不会带来任何好处。一个线程无论如何都会被阻塞,而不是那个调用Task.Run()的线程。

您不需要异步实现每个方法来查看性能的改进(尽管它应该成为始终异步执行I / O的习惯)。

答案 1 :(得分:0)

  

在什么情况下它会减少WCF服务中线程的创建?

如果您有一个等待IO操作的操作(从数据库读取,调用外部Web服务,...),则使用async / await释放正在处理WCF请求的托管线程。这使得线程可用于其他请求,等待IO完成。它可以更有效地使用线程池。

  

在阅读了很多关于async-await之后,我只能在GUI线程中找到使用它的好处

对于客户端应用程序而言,这是我所知道的关键优势,因为与使用服务器应用程序相比,您运行magedd线程的可能性要小得多。

  

有人说使用'等待Task.Run(()=> ...)'不是"真正的异步 - 等待"。

您分配一个新的托管线程来运行新任务,因此您不会保存任何托管线程。