2015-10-08 65 views
0

在阅读了大量有关异步等待的知识后,我只能在GUI线程(WPF/WinForms)中找到使用它的好处。如何处理异步I/O方法

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

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

谢谢你, 斯塔夫。

编辑:

这两个答案都是优秀的,但即使有关如何异步等待的作品,我建议阅读@Stephen克利回答这里瓢解释: https://stackoverflow.com/a/7663734/806963

以下主题都需要理解他的回答: SynchronizationContext,SynchronizationContext.Current,TaskScheduler,TaskScheduler.Current,Threadpool。

+2

'Task.Run'用于在线程池线程上执行cpu-bound代码。真正的异步等待是关于IO限制的代码。 –

+1

这个问题可能看起来太宽泛了,但考虑到正确的答案,它不是。整个概念可以在5段中全面清楚地解释。 –

回答

4

服务器应用程序(如WCF)中异步/等待的真正好处是异步I/O。

当您调用同步I/O方法时,调用线程将被阻塞,等待I/O完成。该线程不能被其他请求使用,它只是等待结果。当更多请求到达时,线程池将创建更多线程来处理它们,浪费大量资源 - 内存,等待线程解除阻塞时的上下文切换...

如果使用异步IO,线程不会被阻止。在启动异步IO操作之后,它可以再次被线程池使用。当异步操作完成时,线程池分配一个线程继续处理请求。没有资源浪费。

MSDN(这是关于文件I/O,但也适用于其他太)

在同步文件I/O,一个线程启动的I/O操作,并立即进入等待状态,直到我/ O请求已完成。执行异步文件I/O的线程通过调用适当的函数向内核发送I/O请求。如果请求被内核接受,调用线程将继续处理另一个作业,直到内核向线程发出I/O操作完成的信号。然后中断它当前的工作并根据需要处理来自I/O操作的数据。

现在,你可能就会明白为什么await Task.Run()不会给予任何好处,如果在任务中的IO同步完成。无论如何,线程都会被阻止,而不是那个叫做Task.Run()的线程。

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

+0

我承认我认为每个调用都不是从threadpull获得新线程。这非常有帮助。虽然逻辑告诉我,如果我创建一个方法(方法1),返回一个任务为其他方法来异步它(调用:await method1())它是一样的做await Task.Run(method1())becouse method1实现返回Task.run(()=>());.所以我没有任何好处来避免它。我正在矫正吗? –

+1

你是对的。要正确实现异步IO而不使用.NET BCL中的现有异步方法,您必须在非常靠近操作系统的较低级别上工作。幸运的是,一切都很好地由.NET BCL处理,所以你可以等待这些方法。 –

0

它在哪些情况下减少了WCF服务中线程的创建?

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

很多阅读有关异步的await之后,我只能找到在GUI线程

对于客户应用程序是我所知道的最重要的优势使用它的好处,因为您比在服务器应用程序中更不可能用尽管理线程。

有人说,使用'await Task.Run(()=> ...)'不是一个“真正的异步等待”。

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

+0

如果我明白,WCF使用线程处理任何请求+任何异步等待操作?所以如果我通过返回新任务来实现我自己的异步等待 - 它并没有真正创建一个,只使用一些线程拉线程而已? –

+0

HTTP请求由线程池处理。 IO操作在挂起时不需要线程。 –

+0

那么你告诉我的是Async-IO opertion不在其他线程上?它的封锁运作呢? –