WCF死鎖三種不同方式介紹
用過WCF的朋友們應該會清楚的認識到,當我們在使用回調契約時,通常會出現死鎖的情況出現。那么如何才能正確的解決WCF死鎖問題呢?我們今天就為大家詳細介紹了幾種解決方案,供大家參考學習。#t#
例如,當客戶端執行服務操作時,向客戶端發出的調用會阻塞服務端進程,以等待服務操作執行完畢。而在該服務操作中,又獲得了回調契約對象的引用(或者獲得保存的回調契約副本),并執行回調操作。由于服務類被配置為單線程訪問,則服務實例是與鎖相關聯的。如果回調對象也需要返回同一個鎖的所有權,簡單的說,就是指當回調的應答消息也需要獲得與服務實例關聯的相同的鎖時,就會導致死鎖。因為此時服務線程已經被阻塞,服務操作正在等待回調操作執行完畢,而回調操作卻又在等待服務釋放鎖,自然會產生鎖的爭用。
解決WCF死鎖的辦法有三個,一個是將服務配置為允許多線程訪問,但這會增加服務開發者管理多線程的負擔。第二個方案是將回調設置為重入(Reentrancy),如下所示:
- [ServiceBehavior(ConcurrencyModeConcurrencyMode =
ConcurrencyMode.Reentrant)]- class MyService : IMyContract
- {
- public void DoSomething( )
- {
- IMyContractCallback callback = OperationContext.Current.
GetCallbackChannel<IMyContractCallback>( );- callback.OnCallback( );
- }
- }
所謂“重入”,是指對同步域擁有獨占訪問權的線程A調用了同步域之外對象的方法,此時,另外的線程B若要訪問該同步域,則線程A將釋放對同步域的鎖,允許線程B進入。直到線程B執行完畢并釋放對同步域的鎖后,線程A將重新進入該同步域。配置回調為重入時,因為服務對象是與線程關聯的,屬于同步域的對象,而回調對象則屬于同步域之外的對象。由于服務被配置為重入,則服務調用回調引用時會釋放鎖。然后將回調返回給客戶端,控制權則返回給服務,服務會重入并重新獲取鎖。這樣就解決了死鎖的問題。
第三種方案則是將回調操作設置為單向操作。此時,回調調用不會產生應答消息,服務操作一旦執行了回調操作,就會繼續執行,回調對象不會爭用與服務實例關聯的鎖,從而解決了WCF死鎖問題。
- interface IMyContractCallback
- {
- [OperationContract(IsOneWay = true)] void OnCallback( );
- }
在使用回調對象時,需要考慮到客戶端代理可能會被關閉,如果此時調用回調,就會引發一個ObjectDisposedException異常。“因此,對于客戶端而言,當它不再需要接收回調或者客戶端應用程序已經關閉時,***能夠通知服務。”本書給出了解決這一問題的方法,就是為服務契約增加兩個操作Connect()與Disconnect()。其中,Disconnect()正是起到了通知服務的作用,它在客戶端代理關閉的情況下,可以將當前的回調對象引用從列表中移除。至于Connect()方法則是出于對稱的目的而引入,但引入它還有一個好處是,它可以使得客戶端能夠多次地連接或斷開。實現Connect()與Disconnect()方法的代碼如下:
- static List<IMyContractCallback> m_Callbacks =
new List<IMyContractCallback>( );- public void Connect( ) {
- IMyContractCallback callback = OperationContext.Current.
GetCallbackChannel<IMyContractCallback>( );- if(m_Callbacks.Contains(callback) == false)
- {
- m_Callbacks.Add(callback);
- }
- }
- public void Disconnect( )
- {
- IMyContractCallback callback = OperationContext.Current.
GetCallbackChannel<IMyContractCallback>( );- if(m_Callbacks.Contains(callback) == true)
- {
- m_Callbacks.Remove(callback);
- }
- else
- {
- throw new InvalidOperationException("Cannot find callback");
- }
- }
以上就是我們為大家介紹的幾種不同的WCF死鎖解決方法。