2016-06-22 49 views

回答

6

正如我在我的博客上描述的那样,long-running I/O operations do not require a thread at all。相反,它们使用自然异步I/O,它不需要线程。

设备驱动程序通常使用DMA,这允许设备直接读/写主系统RAM。 .NET通过作为线程池一部分的IOCP(I/O完成端口)对此方法进行了补充,允许每个AppDomain的单个线程(或极少线程)等待大量的I/O操作。

要回答你的问题的后半部分,异步方法恢复与请求上下文,但它可能会或可能不会是同一个线程是在await之前。更常见的情况是当I/O操作完成时,它向IOCP发出信号,这需要线程池线程进行一些内务处理(将任务标记为完成等),然后该同一线程进入ASP.NET请求上下文并恢复执行处理程序。这不是总是发生 - 有时一个线程切换是必要的 - 但这是最​​常见的情况。

+0

谢谢Stephen Cleary! – Sunny

+0

如果它不是I/O操作会怎么样。如果它是一个在一个函数中执行并且消耗很多时间的业务逻辑。它不会创建一个新的线程。 – Sunny

+0

@Sunny:不可以。如果你在没有await的情况下使用'async',那么代码就直接在调用线程上运行。如果使用'await Task.Run',那么'Task.Run'(*不是'async' /'await')将使用单独的线程池线程(注意:这不建议在ASP.NET上使用)。 –

1

要回答你的问题,所有线程都来自线程池。

可以这样给出一个示例场景,当服务器收到请求时,将从池中提取可用线程来为请求提供服务。

然后你产生一个新的线程(通过Async或其他手段)。现在从池中抽取一个新线程来运行您的Async正文的请求。

同时,原始线程被释放到池中并返回处理另一个请求。

当线程完成时,它从池中取回另一个线程(可能与原始线程不同)并完成请求。

由于您阻止一个线程(来自同一个池),因此如果此进程受到CPU限制,则这会浪费时间。但是,IO绑定操作可以像这样处理,因为它们不使用线程。