程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 並發中的同步--WCF並發體系的同步機制實現

並發中的同步--WCF並發體系的同步機制實現

編輯:關於.NET

在《WCF 並發的本質》中,我們談到了WCF提供的三種不同的並發模式,使開發者可以根據具體的情況 選擇不同的並發處理的策略。對於這三種並發模式,Multiple采用的並行的執行方式,而Single和 Reentrant則是采用串行的執行方式。串行執行即同步執行,在WCF並發框架體系中,這樣的同步機制是如 何實現的呢?

一、Concurrency.Single模式下的同步實現

實際上,WCF並發框架體系下針對Concurrency.Single模式的實現非常簡單,其本質就是對 InstanceContext進行加鎖。如果采用反編譯工具查看InstanceContext的定義,你會發現 InstanceContext類中定義了一個類型為System.Object名為ThisLock的內部屬性,而該屬性實際上就是對 基類CommunicationObject同名屬性的引用,相關代碼入下所示。WCF就是通過對InstanceContext的 ThisLock進行加鎖,確保了對InstanceContext的同步訪問。

1: public sealed class InstanceContext : CommunicationObject,  IExtensibleObject<InstanceContext>
2: {
3:   //其它成員
4:   internal  object ThisLock
5:   {
6:     get
7:     {
8:        return base.ThisLock;
9:     }
10:   }
11: }
12: public abstract  class CommunicationObject : ICommunicationObject
13: {
14:   //其它成員
15:    protected object ThisLock { get; }
16: }

具體來講,WCF服務端運行時在處理服務調用消息請求之後,利用實例上下文提供者 (InstanceContextProvider)創建新的或者獲取現有的InstanceContext。然後,WCF會將請求消息分發 給該InstanceContext對消息進行進一步處理。在處理操作執行之前,如果發現相應的服務采用的並發模 式是ConcurrencyMode.Single,WCF運行時會試圖獲取InstanceContext的ThisLock上的鎖,或者說後續的 操作進行再對InstanceContext的ThisLock鎖定的情況下執行的。這樣就保證了單一的InstanceContext對 象在ConcurrencyMode.Single並發模式下永遠是以同步的方式被調用的。

二、Concurrency.Reentrant模式下的同步實現

在ConcurrencyMode.Single並發模式下,從請求被WCF服務端運行時分發給相應的InstanceContext到 請求處理完成的整個過程中,InstanceContext被鎖定。如果在服務操作執行過程中涉及到對客戶端的回 調,並且回調操作采用請求/回復消息交換模式,當被WCF服務端運行時接收到從客戶端返回的回復消息後 ,會將請求消息再次分發給相同的InstanceContext。運行時分發回調回復消息與普通服務調用請求消息 采用相同的機制,同樣需要在對InstanceContext成功鎖定的情況下進行。很明顯,這樣產生了死鎖 (Deadlock)。

所以,如果在服務操作執行過程中需要對客戶端實施回調,要麼將采用單向(One-way)的方式進行回 調,要麼將服務的並發模式設置成ConcurrencyMode.Reentrant或者ConcurrencyMode.Multiple。否則, 如圖1所示的InvalidOperationException異常會在進行回調操作的時候拋出。從異常消息我們可以看出, VS的漢化真的不敢恭維,如果要正常理解異常消息的含義,你需要知道這裡的“郵件”、“可重輸入”和 “多個”是依次對“Message”、“Reentrant”和“Multiple”的翻譯。

圖1 在Single模式執行回調導致的異常

如果我們真的需要在服務操作過程中實施基於請求/回復模式的回調,毫無疑問采用 Concurrency.Multiple並發模式可以解決死鎖的問題,因為Concurrency.Multiple模式根本就是存在對 InstanceContext加鎖的問題。那麼,在 Concurrency.Reentrant模式下,WCF並發框架體系又是如何解決 這個問題的呢?

Reentrant,翻譯成漢語就是“重入”(VS將其翻譯成“重輸入”簡直莫名其妙),意思是服務操作過 程中完成了對外調用(Call Out)還能重新回到相應的位置繼續執行。同Concurrency.Single模式一樣, WCF運行時將調用請求消息分發給相應的InstanceContext之前,會先對其加鎖。但是,在開始實施回調的 之前,對InstanceContext的鎖定會被解除,當回調返回後再對其加鎖。

對於Concurrency.Reentrant有一點需要特別說明,當服務端進行回調時,由於加載InstanceContext 上的鎖會被釋放,意味著其它服務請求會被分發給該InstanceContext。當回調返回的時候,如果 InstanceContext正被用於才處理在進行回調過程抵達的請求,雖然自己是先來者,依然會等待,因為重 入後的InstanceContext被鎖定。如果等待的時間超過設定的超時時限,客戶端會拋出TimeoutException 異常。

由於WCF的並發是針對某個封裝了服務實例的InstanceContext而言的,所以在不同的實例上下文模式 下,會表現出不同的並發行為。在下一篇文章中,我將從具體的實例上下文模式的角度來剖析WCF的並發 ,敬請期待。

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