為了更好地說明問題,這里我們將標準的foreach操作展開為傳統(tǒng)的迭代器使用形式,并省略了using語句。在使用時,我們先調(diào)用一個IEnumerable對象的GetEnumerator方法,獲得一個迭代器,再根據(jù)MoveNext及Current進行遍歷。在調(diào)用MoveNext時,迭代器會去“準備”下一個元素,并根據(jù)存在與否返回true或者false。試想,如果其中某個MoveNext的“準備”工作涉及到一個耗時較長的操作,則迭代器的使用者也必須眼巴巴地等待其返回。
這是一種“拉(Pull)”模型,數(shù)據(jù)由消費者(Consumer)從生產(chǎn)者(Producer)那里主動“拉”來。這是一種同步的交互方式,數(shù)據(jù)消費者會依賴于數(shù)據(jù)生產(chǎn)者的表現(xiàn)。這就好比我們?nèi)ナ程贸燥垥r必須主動去取餐,此時則必須從隊伍的最后排起,我們什么時候能結(jié)束等待并進行下一步操作(即“吃飯”),則要看食堂的生產(chǎn)速度如何。很顯然,有些時候這種交互方式是不可接受的,例如我們在實現(xiàn)一個搜索引擎的“關(guān)鍵字提示”功能時,不可能讓用戶在輸入一個字符后,必須等待遠程的提示請求返回才能繼續(xù)輸入下一個字符。
而與交互式編程對應(yīng)的便是“響應(yīng)式(Reactive)”編程。響應(yīng)式編程是一種基于“改變”的編程方式。例如在交互式編程中,A = B + C這樣的表達式意味著將B與C之和賦給A,而此后B與C的改變都與A無關(guān)。而在響應(yīng)式編程中,A會去“響應(yīng)”B或C的變化,即一旦B或C改變之后,A的值也會隨之變化。響應(yīng)式編程的一個典型應(yīng)用便是GoF23中的觀察者(Observer)模式。與迭代器的IEnumerable/IEnumerator不同,在之前的.NET框架中并沒有對這樣一種編程模型指定“標準化(Formallized)”接口,不過在.NET 4.0的基礎(chǔ)類庫中增加了IObservable及IObserver接口,簽名如下:
public interface IObservable<out T> { IDisposable Subscribe(IObserver<T> observer); } public interface IObserver<in T> { void OnCompleted(); void OnError(Exception error); void OnNext(T value); }
如果我們仔細比較“迭代器”與“觀察者”的標準化接口,則會發(fā)現(xiàn)它們是完全“對偶(dual)”的:
IEnumerable.GetEnumerator方法“輸出”一個IEnumerater對象;IObservable.Subscribe方法“輸入”一個IObserver對象。
在遍歷元素用盡時,IEnumerator.MoveNext方法返回false;在響應(yīng)內(nèi)容用盡時,IObserver.OnCompleted方法被調(diào)用。
在有新元素需要遍歷時,IEnumerator.MoveNext方法返回true,并通過Current屬性“輸出”;在有新元素需要響應(yīng)時,IObserver.OnNext方法被調(diào)用,并通過參數(shù)“輸入”。
在出現(xiàn)錯誤時,IEnumerator.MoveNext方法會“拋出”一個異常;在出現(xiàn)錯誤時,IObserver.OnError方法會被調(diào)用,并通過參數(shù)“接受”異常信息。
至于IObservable.Subscribe方法返回的IDisposable對象,則用于“退定”操作,即讓輸入的IObserver對象再也不需要繼續(xù)響應(yīng)IObservable對象的新元素了。
從比較中可以看出,如果說IEnumerator對象是由數(shù)據(jù)消費者使用的話,那么IObserver對象則是由數(shù)據(jù)的生產(chǎn)者,即IObservable對象使用的。
換句話說,數(shù)據(jù)是由數(shù)據(jù)的生產(chǎn)者“推”給數(shù)據(jù)消費者的,是一種“推(Push)”模型。在這種異步的交互方式中,數(shù)據(jù)消費者不必依賴于數(shù)據(jù)生產(chǎn)者的表現(xiàn)。這就好比我們?nèi)ワ埖瓿燥,點菜后便可坐下和同伴聊聊天或是用手機上上網(wǎng),而作為菜品的生產(chǎn)者,飯店,則會在產(chǎn)出之后主動端上桌來。這么做無疑解放了數(shù)據(jù)的消費者,例如用戶可以在文本框里不斷地輸入字符,而只需等遠程服務(wù)器將提示結(jié)果“推”給客戶端后再顯示即可。
出處:老趙點滴
責任編輯:bluehearts
上一頁 異步編程與響應(yīng)式框架 [1] 下一頁 異步編程與響應(yīng)式框架 [3]
◎進入論壇網(wǎng)絡(luò)編程版塊參加討論
|