.NET中的異步編程(一):異步編程的原因
微軟在2010年的PDC上發(fā)布了Visual Studio Async CTP,大大地降低了異步編程的難度,讓我們可以像寫同步的方法那樣去編寫異步代碼。Async CTP也在社區(qū)里掀起了不小的波瀾。在這之后,我也學(xué)習(xí)了一段時間,這個系列會將這段時間的學(xué)習(xí)作個梳理。
下面就對為什么要需要異步編程進(jìn)行詳細(xì)的說明。
為什么需要異步編程
既然同步的寫法更自然簡單,異步的代碼(傳統(tǒng)的)不好寫,還容易出錯,那我們?yōu)槭裁葱枰ゾ帉懏惒降拇a呢?微軟還要費這么大勁投入對Async CTP的開發(fā)呢?這其中肯定有一些原因。
快速響應(yīng)的用戶界面
作為電腦的資深用戶,我們肯定有多次“漏斗式鼠標(biāo)”,“轉(zhuǎn)圈式鼠標(biāo)”的體驗吧。點擊一個按鈕,然后鼠標(biāo)就在那兒不停的轉(zhuǎn)圈,再在界面上點兩下,界面變灰,標(biāo)題欄上出現(xiàn)“沒有響應(yīng)”。然后我們束手無策,性子好點的就在那兒等待一會兒,看看能不能恢復(fù)過來;性子不好的就打開任務(wù)管理器殺掉進(jìn)程,殺掉進(jìn)程容易,但有可能會破壞重要數(shù)據(jù)。
那造成這種情況到底是什么原因呢?概括成一句話就是:耗時的操作阻塞了UI線程,造成UI線程不能響應(yīng)用戶操作。關(guān)于更底層的原因請移步我的這篇文章:WinForm二三事(一)消息循環(huán)。那么這個時候我們就需要一種機(jī)制,在發(fā)起耗時操作的請求之后要立即返回,不要阻塞UI線程,讓UI線程可以繼續(xù)響應(yīng)用用戶的操作。然后等耗時操作返回后,通過回調(diào)來處理耗時操作返回的結(jié)果。下面是在UI上使用同步的方式和異步的方式的示意圖:
更高的伸縮性
對于服務(wù)器端應(yīng)用來說,一般都是一個線程處理一個請求。另外一點是,線程的創(chuàng)建和銷毀是昂貴的(這一點可以參考《CLR via C#》中Thread Baisc一章的描述),而服務(wù)器的資源肯定是有限的;并且,線程創(chuàng)建的越多,線程上下文切換就會變得越頻繁。所以,為了創(chuàng)建高可伸縮性的服務(wù),我們必須用最少的線程處理更多的請求,這樣不僅能夠做到消耗更少的資源(創(chuàng)建更少的線程),而且在應(yīng)對請求突發(fā)增長的情況也很有用處,那么這里非常重要的一點就是不要阻塞線程,讓線程池能夠高效的工作。而且,在服務(wù)端應(yīng)用中,有非常多的IO操作:數(shù)據(jù)庫訪問,磁盤操作,Socket訪問等。對于這些IO操作,不屬于計算密集型操作,是不需要單獨分配一個線程來處理的。
要做到高可伸縮性,異步是一劑良藥。假設(shè)現(xiàn)在這是一個web應(yīng)用,當(dāng)用戶的HTTP request到來時,線程池提供一個線程來處理(忽略前面的排隊等過程),然后到某一點,我們肯定需要讀取磁盤、訪問數(shù)據(jù)庫,這個時候我們使用異步的方式,發(fā)起IO請求,然后處理HTTP request的線程就可以返回到線程池了,它可以繼續(xù)處理其他請求,不需要在這里等待IO操作的返回。當(dāng)IO操作完成之后,會通過回調(diào)(具體實現(xiàn)方式請參照后續(xù)文章)完成剛才那個HTTP reqeust后續(xù)的處理。
下面是使用同步方式和異步方式的示意圖:
上圖只畫出了一個請求,高亮顯示的那一段其實是不需要占用線程的,其實這段時間該線程可以返回線程池,然后分配去做其他請求,而數(shù)據(jù)庫返回結(jié)果之后,再從線程池里分配一個線程來處理后續(xù)操作。這樣,如果請求多的話,線程池就會創(chuàng)建更多的線程來處理請求,***結(jié)果大家應(yīng)該都知道了。
從上圖可以看出,開始的時候來自線程池的thread1處理請求,然后發(fā)起對數(shù)據(jù)庫的請求,發(fā)起操作完畢后,thread1被線程池回收;當(dāng)數(shù)據(jù)庫將結(jié)果返回時線程池選擇另外一個線程thread2(有可能是原來的那個線程,如果空閑的話)來處理數(shù)據(jù)庫返回的結(jié)果,完成后續(xù)的操作。對于IO操作非常多的服務(wù)來說,所獲得的益處是不可估量的。
總結(jié)
本文主要從創(chuàng)建響應(yīng)靈敏的用戶界面和創(chuàng)建高可伸縮性的服務(wù)應(yīng)用這兩種不同的應(yīng)用場景來闡釋我們?yōu)槭裁葱枰?STRONG>異步。如何進(jìn)行異步開發(fā)在后續(xù)的文章我會首先介紹傳統(tǒng)的異步和Async CTP以及F#中的Async Workflow。
【編輯推薦】
- .Net reflector兩款神器 Deblector和reflexil
- VS.NET 2010已經(jīng)發(fā)布了beta2版本 新功能
- ASP.NET MVC 3 新特性全解析
- ASP.NET站點構(gòu)建之減少不必要的請求