2011-01-05 84 views
7

我在.NET 4中實現了我的第一個REST服務,並且遇到了意想不到的情況。似乎我不明白微軟ServiceModel的基本工作原理,但無法以傳統方式找到答案。在.NET REST服務實現中使用線程池

要實現我的web服務,我按照這個教程的步驟:http://blogs.msdn.com/b/endpoint/archive/2010/01/06/introducing-wcf-webhttp-services-in-net-4.aspx

的服務工作。令我驚訝的是Global.asax中的Application_BeginRequest和Application_EndRequest被不同的線程調用。看看堆棧跟蹤,看起來這些線程基於某種線程池。

沒有做一些重構,這是我們的一個問題,因爲我們總是假設一個請求總是在同一線程上運行,由於它我們保管存儲在線程本地存儲一些變量。這些變量在Application_BeginRequest中初始化並在Application_EndRequest中發佈。看來,使用ServiceModel這不是正確的方法。

我的問題是:

  1. 我可以做任何假設哪些線程正在運行我的代碼,當我使用ServiceModel?
  2. 有什麼辦法可以將執行限制到單個線程嗎?這會因爲什麼原因而變壞?
  3. 使用ServiceModel時,在請求期間存儲變量的正確方法是什麼?

謝謝。

+0

更新,對最初的問題。它的一個線程調用Application_BeginRequest,另一個線程運行服務代碼並執行Application_EndRequest。改變ServiceBehavior params沒有做任何事情。任何幫助將非常感激。 – Alex 2011-01-05 22:33:14

+0

聽起來像你正在使用asp.net兼容性的東西,或嘗試。你嘗試過實現你的東西作爲消息調度,或任何其他wcf擴展點(而不是使用asp.net)? – sisve 2011-01-06 00:19:16

+0

@Simon Svensson我正在關注微軟的教程http://blogs.msdn.com/b/endpoint/archive/2010/01/06/introducing-wcf-webhttp-services-in-net-4.aspx。這似乎確實使用了asp.net兼容性。如果使用其他方法,會有什麼不同?有沒有一個我可以閱讀的好地方?謝謝! – Alex 2011-01-06 01:22:00

回答

0

你可能想看看你的服務實現[ServiceBehavior]屬性,因爲它支持的參數來控制許多情況下獲得創建和使用什麼的線程模型。

http://msdn.microsoft.com/en-us/library/cc681240.aspx

當你有

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, 
       ConcurrencyMode = ConcurrencyMode.Multiple)] 
public class MyService : IMyService 

您的服務將運行一個單,但多線程 - 直至在WCF配置設置的閾值 - 調用到你的方法。要強制它僅在一個線程上運行,並因此序列化入站請求,請設置ConcurrencyMode.Single。

或者,你可以旋轉你的服務的一個新實例每次調用:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, 
       ConcurrencyMode = ConcurrencyMode.Single)] 
public class MyService : IMyService 

的實例將只有一個線程訪問它。事實上,當你有InstanceContextMode.PerCall時,那麼ConcurrencyMode會被忽略,因爲它總是「Single」,並且每個實例都在它自己的線程中運行。

+0

謝謝勞倫斯。 我設置 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)] 但主叫 Thread.CurrentThread.GetHashCode()。的ToString() 上的Application_BeginRequest和Application_EndRequest返回不同價值觀,我是否做了其他不正確的事情? – Alex 2011-01-05 20:16:26

2

有一件事我建議是考慮使用WCF掛鉤,而不是和的Application_BeginRequest方法Application_EndRequest。四個實例,這裏有更多有用的鉤子四:

AfterReceiveRequest - > BeforeCall - >方法的調用 - > AfterCall - > BeforeSendReply

有掛鉤是非常強大的。在調用方法之前調用參數(將某些日誌記錄集中到一個位置)並執行各種其他有用的操作。這些不是唯一可用的鉤子,還有一些我也使用。例如GetInstance允許我重寫服務類對象的創建(所以你可以使用依賴注入框架等)。

當我使用每次通話併發模式,這些掛鉤再加上方法調用本身都得到所謂的在同一線程上。希望這可以幫助。如果你願意,我可以提供實現這些鉤子的鏈接。

乾杯