.NET中的異步

.NET中4種異步方式?

  1. ThreadPool.QueueUserworkItem實現
  2. APM模式(就是BeginXXX和EndXXX成對出現。)
  3. EAP模式(就是Event based, 準確說來就是任務在處理中或者處理完成,會拋出事件)
  4. Task
Thead vs Task(4.0)
1.實例化一個Thread建立的是前臺線程(能夠經過修改Thread的IsBackground,將其變爲後臺線程)
2.Task啓動的線程是後臺線程,不過能夠經過在Main方法中調用task.Wait()方法,使應用程序等待task執行完畢
3.Task與Thread的一個重要區分點是:Task底層是使用線程池的,而Thread每次實例化都會建立一個新的線程。

ASP.NET請求是如何處理的?

每一個 ASP.NET 請求都要先經過 IIS,而後再由 ASP.NET 處理程序進行最終處理。 首先IIS 接收請求,初步處理後,發送給ASP.NET(必須是一個ASP.NET請求),而後由ASP.NET進行實際處理並生成響應,以後該響應經過IIS發回給客戶。在IIS上,有一些工做進程負責從隊列中取出請求,並執行IIS 模塊,而後再將該請求發送到ASP.NET 隊列。可是,ASP.NET自己不建立任何線程,也沒有處理請求的線程池,而是經過使用CLR 線程池,從中獲取線程來處理請求。所以,IIS 模塊調用ThreadPool.QueueUserWorkItem,將請求排入隊列,供CLR 工做線程處理。咱們都知道,CLR線程池是由CLR管理,而且可以自動調整(也就是說,它根據須要建立和銷燬進程)。這裏還要記住,建立和銷燬線程是項很繁重的任務,這就是爲何CLR線程池容許使用同一個線程處理多個任務。下面來看一個描述請求處理過程的圖示。web

充分發揮異步在 ASP.NET 中的強大優點 技術分享

在上圖中能夠看到,請求首先由 HTTP.sys接收,並添加到相應內核級應用程序池隊列。而後,一個IIS工做線程從隊列中取出請求,處理後將其傳到ASP.NET 隊列。注意,該請求若是不是一個ASP.NET請求,將從 IIS 自動返回。最後,從CLR線程池中分配一個線程,負責處理該請求。數據庫

ASP.NET中異步的使用場景是?

1. 基於線程池的請求處理服務器

ASP.NET經過線程池的機制處理併發的HTTP請求。一個Web應用內部維護着一個線程池,當探測到抵達的針對本應用的請求時,會從池中獲取一個空閒的線程來處理該請求。當處理完畢,線程不會被回收,而是從新釋放到池中。線程池具備一個線程的最大容量,若是建立的線程達到這個上限而且全部的線程均被處於「忙碌」狀態,新的HTTP請求會被放入一個請求隊列以等待某個完成了請求處理任務的線程從新釋放到池中。網絡

咱們將這些用於處理HTTP請求的線程稱爲工做線程(Worker Thread),而這個縣城池天然就叫作工做線程池。ASP.NET這種基於線程池的請求處理機制主要具備以下兩個優點:併發

  • 工做線程的重用:建立線程的成本雖然不如進程的激活,卻也不是一件「一蹴而就」的事情,頻繁地建立和釋放線程會對性能形成極大的損害。而線程池機制避免了老是建立新的工做線程來處理每個請求,被建立的工做線程獲得了極大地重用,並最終提升了服務器的吞吐能力。
  • 工做線程數量的限制:資源的有限性具備了服務器處理請求的能力具備一個上限,或者說某臺服務器可以處理的請求併發量具備一個臨界點,一旦超過這個臨界點,整臺服務將會因不能提供足夠的資源而崩潰。因爲採用了對工做線程數量具備良好控制的線程池機制,ASP.NET MVC併發處理的請求數量不可能超過線程池的最大容許的容量,從而避免了在高併發狀況下工做線程的無限制建立而最致使整個服務器的崩潰。

若是請求處理操做耗時較短,那麼工做線程處理完畢後能夠及時地被釋放到線程池中以用於對下一個請求的處理。可是對於比較耗時的操做來講,意味着工做線程將被長時間被某個請求獨佔,若是這樣的操做訪問比較頻繁,在高併發的狀況下意味着線程池中將可能找不到空閒的工做線程用於及時處理最新抵達請求。異步

若是咱們採用異步的方式來處理這樣的耗時請求,工做線程可讓後臺線程來接手,本身能夠及時地被釋放到線程池中用於進行後續請求的處理,從而提升了整個服務器的吞吐能力。值得一提的是,異步操做主要用於I/O綁定操做(好比數據庫訪問和遠程服務調用等),而非CPU綁定操做,由於異步操做對總體性能的提高來源於:當I/O設備在處理某個任務的時候,CPU能夠釋放出來處理另外一個任務。若是耗時操做主要依賴於本機CPU的運算,採用異步方法反而會由於線程調度和線程上下文的切換而影響總體的性能。高併發

2.使用場景性能

全部請求大體能夠分爲兩類:spa

1. CPU Bound 類 
2. I/O Bound 類線程

CPU Bound 類請求,須要 CPU 時間,並且是在同一進程中執行;而 I/O Bound 類請求,自己具備阻塞性,須要依賴其餘模塊執行 I/O 操做並返回響應。阻塞性請求是提升應用程序可伸縮性的主要障礙,並且大多數web應用程序中,在等待 I/O 操做的過程當中浪費了大量時間。 所以如下場景適合使用異步:

    1. I/O Bound 類請求,包括:

      a. 數據庫訪問

      b. 讀/寫文件

      c. Web 服務調用

      d. 訪問網絡資源

    2. 事件驅動的請求,好比SignalR

    3. 須要從多個數據源獲取數據的場景

相關文章
相關標籤/搜索