【发布时间】:2016-06-22 12:41:43
【问题描述】:
对于长时间运行的操作,如果 asp.net 线程被释放到服务器其他请求。长时间运行的操作将在哪个线程上执行,完成后如何获取 asp.net 线程。
【问题讨论】:
标签: c# asp.net multithreading
对于长时间运行的操作,如果 asp.net 线程被释放到服务器其他请求。长时间运行的操作将在哪个线程上执行,完成后如何获取 asp.net 线程。
【问题讨论】:
标签: c# asp.net multithreading
正如我在博客中所描述的,long-running I/O operations do not require a thread at all。相反,它们使用不需要线程的自然异步 I/O。
设备驱动程序通常使用 DMA,这允许设备直接读取/写入主系统 RAM。 .NET 通过作为线程池一部分的 IOCP(I/O 完成端口)补充了这种方法,允许每个应用程序域的单个线程(或很少的线程)等待大量 I/O 操作。
要回答您问题的后半部分,异步方法将恢复请求上下文,但它可能会或可能不会在它所在的同一线程上在await 之前。更常见的情况是,当 I/O 操作完成时,它会向 IOCP 发出信号,IOCP 需要一个线程池线程来做一些内务处理(将任务标记为完成等),然后同一个线程进入 ASP.NET请求上下文并继续执行处理程序。这并不总是发生 - 有时线程切换是必要的 - 但这是最常见的情况。
【讨论】:
async而不使用await,那么代码只是直接在调用线程上运行。如果你使用await Task.Run,那么Task.Run(notasync/await)使用单独的线程池线程(注意:在 ASP.NET 上不建议这样做)。
回答你的问题,所有线程都是从线程池中抽取的。
可以这样给出一个示例场景,当服务器接收到请求时,会从池中抽取一个可用线程来为请求提供服务。
然后你生成一个新线程(通过Async 或其他方式)。现在从池中抽取一个新线程来运行Async 主体的请求。
同时原始线程被释放到池中并返回处理另一个请求。
当您的线程完成后,它会从池中取回另一个线程(可能与原始线程不同)并完成您的请求。
如果此进程受 CPU 限制,那完全是浪费时间,因为您阻塞了一个线程(来自同一个池)。但是 IO 绑定操作可以像这样处理,因为它们不使用线程。
【讨论】: