2010-11-18 61 views
3

我們有一個Web服務,它將請求發送到託管WCF服務進行處理的Windows服務。Windows服務/ WCF和線程,初學者問題

界面簡單:

namespace MyApp 
{ 
    [ServiceContract] 
    public interface IMyApp 
    { 
     [OperationContract] 
     string DoSomething(string xml); 
    } 
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] 
    class MyAppWcf : IMyApp 
    { 
     public string DoSomething(string xml) 
     { 
      Customer customer = GlobalObject.GetCustomer(xml); //millisecs 
      return customer.DoSomething(xml); //Takes 5-10 seconds 
     } 
    } 
} 

GlobalObject是在WindowsService.OnStart()實例化,幷包含所有靜態數據的客戶對象需要。 界面DoSomething()將被調用到約。 30個不同的客戶。

問題:
1.什麼是現在的默認線程行爲?每次通話都必須等到最後一次通話完成?
2.什麼影響會改變InstanceContextMode?

REAL問題:
有多達1000個客戶對象,2個不同的客戶對象可以被稱爲並行,但同樣缺一不可。例如
DoSomething(「Customer 1」); =>繼續。在10秒內回答
DoSomething(「Customer 2」); =>與上述呼叫同時進行。
DoSomething(「Customer 2」); =>將等待DoSomething(「客戶2」)的最後一次呼叫完成

我的服務行爲設置應該如何,我必須實現鎖定機制以防止同時處理多個並行對象?

謝謝。

編輯2:GlobalObject.GetCustomer()只是從字典中檢索XML中提到的客戶。

回答

2

好的。我不確定我知道ConcurrencyMode在使用PerCall實例化時被忽略,但是看看我自己的項目,我使用PerCall實例化,並且沒有爲ConcurrencyMode指定任何值。顯然,我確實知道這一點,只是沒有在我的代碼中記錄它。現在糾正了。

我的項目與您描述的很相似,我使用InstanceContextMode.PerCall,因爲我已經提到過。這就是這個意思。

  • 客戶端1 =>MyAppWcfInst.DoSomething("<customer id=A/>");
  • 客戶端2 =>MyAppWcfInst.DoSomething("<customer id=B/>");
  • Client3 =>MyAppWcfInst.DoSomething("<customer id=B/>");

所有這三個客戶端將同時與WCF服務交互,但他們每個人都會有自己的實例並在一個單獨的線程內運行。因此,雖然每個客戶端的每個呼叫都是單線程的,但它們可以同時處於活動狀態。這意味着客戶對象列表可以被多個客戶同時訪問。

客戶端1和客戶端2可以並行操作,因爲它們處理不同的客戶對象,但客戶端3需要等到客戶端2完成後才能夠與客戶端「做些什麼」。所有這一切意味着您需要在每個Customer對象中同步訪問。換句話說,Customer.DoSomething()方法中的邏輯需要有一個同步鎖定,以防止多個客戶端同時在客戶端操作。

class Customer 
{ 
    private object _sync = new object(); 

    public string DoSomething(string xml) 
    { 
     lock (_sync) 
     { 
      // put your logic here... 
     } 
    } 
} 

這是我的WCF服務的工作方式。希望這可以幫助。

+0

感謝馬特,那看起來正是我所需要的。 – 2010-11-19 21:27:05

1

使用PerCall,您將獲得對並行處理的服務的請求,每個服務都在MyAppWcf類的不同實例上。如果沒有可用的免費.NET線程池線程來分派它們,請求將只需等待較早的一個完成。 如果將其更改爲Single,那麼請求將被序列化,除非將ConcurrencyMode設置爲Multiple。

你真正的擔心應該是如何安全的併發訪問GobalObject方法是:如果這不是安全的,上面的代碼也不是。

與Customer.DoSomething方法類似,如果它觸及任何共享數據(如本身調用GlobalObject)。

我不明白你的意思是「一次只能處理一個客戶對象」。如果這是真的,那麼你需要避免平行執行。

+0

可能有1000個客戶對象。每個客戶對象本身都是線程安全的,但同一個客戶對象不能同時運行。例如客戶1和客戶2可以並行處理。 GlobalObject.GetCustomer是安全的(只讀)。 – 2010-11-18 16:38:46

+1

Re Matt Davis的回答......我一直都明白,當InstanceContextMode是PerCall時,ConcurrencyMode被忽略,這就是MSDN文檔所說的。所以我認爲你已經有了並行執行的功能......但我會檢查一下,以防文檔錯誤。 – 2010-11-18 18:40:17

+0

+1 @Chris Dickson。我根據這些信息更新了我的回覆,顯然我一直在這個方面忘了。謝謝。 – 2010-11-19 03:11:36