2012-07-31 49 views
1

我已經邁出了使用WCF開發WINDOWS服務託管計算引擎的第一步。該服務工作的很好,但它似乎只使用一個線程爲我所有的電話,但我需要它是可擴展的,並使用多線程。自託管的WCF服務:ConcurrencyMode.Multiple但僅使用一個線程?

忽略代碼中的所有跟蹤等,因爲它是這個應用程序的非常早期的階段。

它調用一些在服務啓動時將信息讀入內存的第三方軟件(ThirdParty.Initialise(strInit)),然後每次調用ProcessInformation都會返回給定XML字符串的計算結果。

到目前爲止,無論我設置ServiceBehavior atts以及無論使用多少獨立的消費者,所有調用都只使用一個線程 - 任何人都可以提供幫助嗎?

代碼概述:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall, UseSynchronizationContext = false)] 
public class TestWCFService : ITestWCFService 
{ 
    private static ThirdPartyLib.ThirdPartyComClass ThirdParty; 

    private static bool initCalled = false; 
    private static int cntInit = 0; 
    private static int cntTrans = 0; 

    public TestWCFService() 
    { 
     if (ThirdParty == null) 
     { 
      ThirdParty = new ThirdPartyLib.ThirdPartyComClass(); 
     } 
    } 

    public bool InitialiseThirdParty(string strInit, out string strError) 
    { 
     try 
     { 
      if (!initCalled) 
      { 
       cntInit++; 
       ThirdParty.Initialise(strInit); 
       initCalled = true; 
      } 
      strError = "Call Num " + cntInit; 
      return true; 
     } 
     catch (Exception ex) 
     { 
      strError = "ThirdParty.Initialise exception " + ex.Message + " 0n call number " + cntInit; 
      return false; 
     } 
    } 

    public bool ProcessInformation(string strRequestXML, int quoteMarker, out string strResponseXML, out string strError, out int quoteMarkerReturned) 
    { 
     try 
     { 
      cntTrans++; 
      quoteMarkerReturned = quoteMarker; 
      ThirdParty.ProcessInformation(strRequestXML, out strResponseXML); 
      strError = "Call Trans Num " + cntTrans; 
      return true; 
     } 
     catch (Exception ex) 
     { 
      strError = ex.Message + " On call trans num " + cntTrans; 
      strResponseXML = "Error"; 
      quoteMarkerReturned = quoteMarker; 
      return false; 
     } 
    } 
} 

配置:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.web> 
    <compilation debug="true" /> 
    </system.web> 
    <system.serviceModel> 
    <bindings> 
     <wsHttpBinding> 
     <binding name="TestServiceBinding" bypassProxyOnLocal="true" 
      useDefaultWebProxy="false"> 
      <readerQuotas maxDepth="524288" maxStringContentLength="524288" 
      maxArrayLength="524288" maxBytesPerRead="524288" maxNameTableCharCount="524288" /> 
      <reliableSession inactivityTimeout="00:30:00" enabled="true" /> 
     </binding> 
     </wsHttpBinding> 
     <mexHttpBinding> 
     <binding name="MEXTestServiceBinding" openTimeout="00:02:00" 
      sendTimeout="00:02:00" /> 
     </mexHttpBinding> 
    </bindings> 
    <services> 
     <service behaviorConfiguration="TestWcfServiceLibrary.TestWCFServiceBehavior" 
     name="TestWcfServiceLibrary.TestWCFService"> 
     <endpoint address="" binding="wsHttpBinding" bindingConfiguration="TestServiceBinding" 
      name="" contract="TestWcfServiceLibrary.ITestWCFService"> 
      <identity> 
      <dns value="localhost" /> 
      </identity> 
     </endpoint> 
     <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="MEXTestServiceBinding" 
      contract="IMetadataExchange" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:8731/Design_Time_Addresses/TestWcfServiceLibrary/TestWCFService/" /> 
      </baseAddresses> 
     </host> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="TestWcfServiceLibrary.TestWCFServiceBehavior"> 
      <serviceMetadata httpGetEnabled="True"/> 
      <serviceThrottling maxConcurrentCalls="100" maxConcurrentSessions="100" maxConcurrentInstances="100"/> 
      <serviceDebug includeExceptionDetailInFaults="False" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    </system.serviceModel> 
</configuration> 
+0

你怎麼知道只有一個線程被使用?我猜想你的第三方COM組件是Apartment線程,因此具有線程關聯性,所以無論服務實現使用多少.NET線程,它們都必須排隊以使用唯一的STA線程能夠調用COM對象。 – 2012-07-31 12:32:13

回答

1

每微軟文檔:

使用併發的是有關實例化模式。在PerCall 實例中,併發性並不相關,因爲每個消息都是由新服務實例處理的 。

// Multiple allows concurrent processing of multiple messages by a service instance. 
// The service implementation should be thread-safe. This can be used to increase throughput. 
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)] 

// Uses Thread.Sleep to vary the execution time of each operation. 
public class CalculatorService : ICalculatorConcurrency 
{ 
    int operationCount; 

    public double Add(double n1, double n2) 
    { 
     operationCount++; 
     System.Threading.Thread.Sleep(180); 
     return n1 + n2; 
    } 

    public double Subtract(double n1, double n2) 
    { 
     operationCount++; 
     System.Threading.Thread.Sleep(100); 
     return n1 - n2; 
    } 

    public double Multiply(double n1, double n2) 
    { 
     operationCount++; 
     System.Threading.Thread.Sleep(150); 
     return n1 * n2; 
    } 

    public double Divide(double n1, double n2) 
    { 
     operationCount++; 
     System.Threading.Thread.Sleep(120); 
     return n1/n2; 
    } 

    public string GetConcurrencyMode() 
    { 
     // Return the ConcurrencyMode of the service. 
     ServiceHost host = (ServiceHost)OperationContext.Current.Host; 
     ServiceBehaviorAttribute behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>(); 
     return behavior.ConcurrencyMode.ToString(); 
    } 

    public int GetOperationCount() 
    { 
     // Return the number of operations. 
     return operationCount; 
    } 
} 

輸出示例:([]中的數字表示螺紋ID)

2012-07-31 09:07:28,509 [9] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 752.919376325402 
2012-07-31 09:07:28,512 [17] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 752.919376325402 
2012-07-31 09:07:28,524 [13] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 2143.10173334651 
2012-07-31 09:07:28,524 [11] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 15.5665354410031, double n2 = 48.3678194919451) 
2012-07-31 09:07:28,532 [22] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 94.7194438868758, double n2 = 29.8120223590229) 
2012-07-31 09:07:28,534 [9] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 99.2045067247024, double n2 = 88.4957458770349) 
2012-07-31 09:07:28,539 [4] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 99.2045067247024, double n2 = 88.4957458770349) 
2012-07-31 09:07:28,539 [7] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 37.991849630136, double n2 = 41.7864370820049) 
2012-07-31 09:07:28,539 [17] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 11.331077670367, double n2 = 55.5888338273339) 
2012-07-31 09:07:28,539 [11] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 752.919376325402 
2012-07-31 09:07:28,539 [22] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 2823.77817898976 
2012-07-31 09:07:28,539 [17] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 629.881393702645 
2012-07-31 09:07:28,542 [9] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 8779.17681696586 
2012-07-31 09:07:28,544 [4] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 8779.17681696586 
2012-07-31 09:07:28,544 [7] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 1587.54403419867 
+0

我真的很希望它那麼簡單。我已經嘗試過這些技巧的每一個配置,沒有任何東西似乎有所作爲。只有一個線程被使用。 – Skyline 2012-07-31 12:08:14

+0

我不確定它是否使用僅使用一個線程的第三方DLL。 – Skyline 2012-07-31 12:10:50

+0

那麼,你的服務是不是線程安全的開始。你在InitialiseThirdParty中有一個競速條件。我會測試示例代碼,如果我可以得到多個線程產卵。你的測試方法是什麼?你怎麼知道你只有一個線程? – Darek 2012-07-31 12:14:15

2

看來很可能是你的第三方COM組件是獨立的線程,因此具有線程關聯。如果是這樣,將只有一個線程在COM組件中進行工作。

然而,許多.NET線程正在被服務實現使用,它們都將不得不排隊使用特定的STA線程,這是唯一能夠調用COM對象的線程。

+0

確實是正確的。我確信它是多線程的,但通過運行替換函數它現在是100%的第三方問題,感謝所有的快速反應,無論如何球員。看起來像一些奇特的步法,使用一些額外的核心可能需要:(。 – Skyline 2012-07-31 15:47:17

+0

分享花哨的步法,如果你可以...永遠不會太晚瞭解一件或兩件事。 – Darek 2012-08-01 01:30:14

0

問題是第三方DLL只是一個單線程的COM模型。我導致認爲它是多線程的,但通過運行替代功能,現在它成爲第三方的問題。無論如何,感謝所有人的快速反應。看起來像一些奇特的步法,可能需要使用一些額外的核心。我發送了一封電子郵件給公司,看他們是否有MT版本,但我對此表示懷疑。再次感謝。

+0

如果您的問題得到解決,請將其標記爲已回答。 – ErnieL 2012-08-01 20:39:16