2016-06-22 74 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綁定操作可以像這樣處理,因爲它們不使用線程。