程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 扯淡異步

扯淡異步

編輯:C#入門知識

 

之前甚至看到有人調侃在搗鼓泛型約束的人說現在時4.0了,不要再搗鼓2.0的泛型了,要與時俱進開始整異步。當然本人有噴子的潛質,所以我就噴了那個人說異步的概念遠比泛型早多了,可以算是古董了。

 

         因為現在做C++,對C#這邊倒漸漸生疏了下來,尤其4.0,很多東西都是靠浏覽園子裡面的文章來補充知識。所以到現在我也不知道為什麼4.0了異步就開始熱火了,畢竟這個真的是古董級別的,一點都不比雲計算的概念來得年輕,都不知道是上個世紀哪個旮旯年代就被提出來了,雲計算一直因為種種原因基本與世隔絕,直到當下取了個洋氣的名字才開始風行。而異步卻很早就滲入到了程序員的級別,無論linux還是windows上C++的編程,異步是一個很正常的處理問題的方法。

 

         下面就轉入正題,說說C#的異步吧,也趕一會潮流,雖說到現在我也不知道為什麼異步現在如此火熱,園子裡首頁基本天天看到異步。

 

         要講異步不得不首先提到同步,就像說一個人的性格,不得不扯上他得胞兄,雖說他的胞兄很無辜,但這個世界上有些事情總要有些人做些陪襯,即使他本來可能更出色。

 

         有人說同步就是對講機,異步就是電話機。但我總覺得類比是個蛋疼的玩意,畢竟即使B與A真的很像,但畢竟不同,B永遠不是A。一類比就意味著你已經漏了很多原汁原味的東西,更壞的結果就是類比讓人開始了南轅北轍,緣木求魚。所以我還是建議能看英文的就盡量看英文,再不濟你看看msdn也行,對於windows下的開發而言,msdn真的是奢侈品,等哪天你遇到問題你不得不去查看源碼,而沒有幫助手冊的時候你才會發現啊,原來曾經我們生活在天堂啊。當然微軟的源碼問題也一直被诟病,畢竟他很多都不開源。

 

         下面解釋下關於同步異步的定義吧。

 

         同步:等待函數執行後返回

 

         異步:不等待函數的執行而直接返回

 

         相信大家小學的時候都學過統籌方法吧,華羅庚那個,說燒開水的。那篇文章講得就是異步。忘記了也沒關系,反正我要改編。

 

比如,想泡壺茶喝。當時的情況是:開水沒有;水壺要洗,茶壺茶杯要洗;火生了,茶葉也有了。怎麼辦?

 

辦法甲:洗好水壺,灌上涼水,放在火上;等待水開,水開了後去洗茶壺、洗茶杯、拿茶葉;泡茶喝。

 

辦法乙:洗好水壺,灌上涼水,放在火上;燒水的同時去洗茶壺、洗茶杯、拿茶葉;等水開,泡茶喝。

 

 

    看完這個,應該很清楚什麼叫同步什麼叫異步了。    同步就是你干事一個個順著干,干完這個干那個。異步就是你把這個安排下然後就去干別的事了,而這件事就被你安排給別人去干了,你只問結果。(當然實際上你是可以不問結果的,對於有些事情,假如你不在意其結果的話。)         也許你會問我,第二種模式下假如在洗茶杯的時候水開了咋辦啊,其實不怎麼辦,直接去把火關了,然後再去洗茶杯。當然這時你又會問我,那我洗茶杯的時候,我怎麼知道水開了啊?

 

         這裡面涉及一個觀察者模式,別怕,這些神馬模式都是扯淡的浮雲,我說了具體實現方法估計你又要雨停了,天晴了,你又覺得你行了。其實在C#裡面有一個東西叫事件,當然java也有啊,這裡只是局限於園子是C#的(主要是C#的)就拿C#說事了。水燒開了,你直接觸發那個事件就OK了,而我,也就是這裡面的主角,事先注冊了這個事件的響應方法就行了,這裡就是去關火。

 

         又扯遠了,下面繼續回來扯同步異步。

 

         相信此時你對什麼是同步什麼是異步很清楚了。

 

 

 

         C#下面最簡單的同步就是你寫的最基本的順序方法,做事一個跟著一件,後來遇到跨線程調用UI線程的東西,你發現C#竟然不准跨線程干這個事情,於是msdn又告訴了你一個方法Invoke。於是空氣又清晰了。

 

         異步,後來你發現有時候有些事情真耗時,而我可不想給用戶這個體驗,連CPU都知道決不讓自己閒著,那麼我們更不能讓線程阻塞著。於是我們想到了異步。於是msdn又告訴了我們BeginInvoke,當然順帶你又瞟到了EndInvoke與IAsyncResult。於是你學會了這東西怎麼用了。

 

       現在我想問的是,這兩個東西他們開銷的資源是誰的啊?

 

       同步你理所當然認為是當前線程的,異步你就開始迷糊了。

 

       上面的例子中,無論是同步還是異步,燒水這個事情開銷的都是煤氣灶的資源,是他在燒水,而不是你在燒水。這個時候就要看我們系統的邊界了,如果我們的邊界是人、煤氣灶、水壺、水、茶葉等等所有資源,那麼開銷的都是系統的資源。無論同步還是異步,只是異步能讓當前線程解放出來,而從線程池裡面找了個煤氣灶出來,讓其負責去燒水。而同步的狀況下就是當前線程在傻傻的燒水,從用戶體驗來說,異步明顯好過同步,因為當前線程不會阻塞在那個傻×點上面。但線程池的畢竟也是線程,線程的切換需要開銷資源,所以異步相對而言多開銷資源了。

 

       我們編程也一樣,組件多了或者線程多了必然帶來哪些不必要的浪費。但有時候這種浪費是必要的,而且是經濟的。

 

       上面說的系統邊界包括了所有,第二種就是系統邊界就是人,那麼燒水開銷的就是外部資源了,這個時候同步的話,系統是不開銷燒水的資源,但卻要傻傻的開銷等水燒開的資源,於是實際上系統是開銷了燒水的時間資源,當然這裡不會包括空間資源。但異步的話,卻只開銷一個水燒開後的泡茶葉的資源,而不必開銷那個傻等的資源。但這裡面涉及一個通信也就是水壺需要告訴你水開了這個消息,這裡面就涉及到了回調函數,於是就涉及到了另一個資源開銷,系統態、用戶態切換的資源消耗,但通常情況下和等水燒開開銷的時間資源完全不是一個檔次。所以此處異步相對同步來說,好處已經不是一兩點了。

 

       也許你也發現了我上面在玩弄文字游戲,於是你覺得這個作者真是個不懂技術的人,只會扯淡。恩,我的確很喜歡扯淡,不然怎麼扯出一篇文章啊。

 

       但如果你自己獨立做過幾個系統你會發現好像又有點道理,不是純粹扯淡。

 

       在我們做簡單的管理系統的時候以及一些簡單單機app的時候,不涉及外設,我們所遇到的東西都是我們系統內的,這個時候異步純粹是為了交互體驗,總資源消耗並不會真的變少,因為這裡的異步其實就是個多線程而已,減少的是時間資源,但也增加了空間資源。

 

       但假如我們做的涉及台位之間通信的app,那麼這個時候對於通信部分的異步或者和外設之間的異步就不再是多線程那麼簡單了。如socket的異步重疊或者IOCP,煤氣灶已經是外部資源了,煤氣灶燒水並不會增加CPU的負載,只有等到誰燒開了通知CPU,CPU才會開始消耗資源,也就是泡茶葉。

 

 

 

相信很多人都對異步搗鼓過,都想過這東西用多線程不也能實現異步。但線程的創建和自殺都是消耗CPU的,我們沒事還是別折磨CPU的好。所以雖然我們上面說的第一種系統邊界,微軟也用了線程池這個概念,為的就是別折磨CPU了,畢竟他是我們的老祖宗,你折磨他,他就折磨你的用戶,反過來你的用戶就要來折磨你了。對於第二種系統邊界,千萬別沒事用多線程去模擬異步,那更是閒的蛋疼,小心你的用戶不付你錢。

 

異步的東西就扯這麼多了,文章裡面有些東西可能存在問題,很多都是我自己的理解,所以估計出問題的概率較大,還望閱讀此文的你對其中錯誤予以指正,對於不足予以補充。

作者BLoodMaster

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved