2012-07-31 2 views
1

나는 WCF를 사용하여 WINDOWS 서비스 호스팅 Calc 엔진을 개발하는 첫 발을 내디뎠다. 서비스는 훌륭하게 작동하지만 모든 호출에 대해 하나의 스레드 만 사용하는 것처럼 보이지만 확장 가능하고 멀티 스레딩을 사용해야합니다.자체 호스팅 WCF 서비스 : ConcurrencyMode.Multiple하지만 하나의 스레드 만 사용하고 있습니까?

이 응용 프로그램의 초기 단계이므로 코드의 모든 추적을 무시하십시오.

서비스 시작시 메모리로 정보를 읽는 (ThirdParty.Initialise (strInit)) 일부 타사 소프트웨어 (COM)를 호출 한 다음 ProcessInformation을 호출 할 때마다 주어진 XML 문자열에서 계산 된 결과가 반환됩니다.

지금까지 모든 호출은 ServiceBehavior를 설정 한 것과 상관없이 하나의 스레드를 사용하는 것처럼 보였습니다. 얼마나 많은 개별 소비자가 사용하던간에 - 아무도 도움이 될 수 있습니까?

코드 개요 :

[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

하나의 스레드 만 사용된다는 것을 어떻게 알 수 있습니까? 귀하의 제 3 자 COM 구성 요소가 아파트 스레드이며 그래서 스레드 친 화성을 가지고있는 것 같아요. 그러나 많은 .NET 스레드가 서비스 구현에 사용되고 있습니다. 그들은 유일한 STA 스레드를 사용하기 위해 모두 대기열에 있어야합니다. COM 개체를 호출 할 수 있습니다. –

답변

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; 
    } 
} 

샘플 출력 :

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

나는 그것이 그렇게 단순하다면 정말로 좋겠다. 나는 그 atts의 모든 구성을 시도하고 아무 것도 차이를 만드는 것 같다. 하나의 스레드 만 사용됩니다. – Skyline

+0

하나의 스레드 만 사용하는 타사 DLL을 사용하는지 확실하지 않습니다. – Skyline

+0

글쎄, 당신의 서비스는 쓰레드로부터 안전하지 않다. InitialiseThirdParty에 경주 조건이 있습니다. 스폰하기 위해 여러 스레드를 얻을 수 있다면 샘플 코드를 테스트 해 보겠습니다. 당신의 테스트 방법은 무엇입니까? 하나의 스레드 만 가지고 있음을 어떻게 알 수 있습니까? – Darek

2

그것은 당신의 타사 COM 구성 요소는 아파트 스레드는 것을 확실히 것으로 보인다 따라서 스레드 친화력이 ([]의 수는 스레드 ID를 나타냅니다). 그렇다면 COM 구성 요소 내에서 작업을 수행하는 스레드는 하나뿐입니다.

많은 .NET 스레드가 서비스 구현에서 사용되고 있지만 COM 개체를 호출 할 수있는 유일한 STA 스레드를 사용하기 위해 모두 대기열에 있어야합니다.

+0

실제로 맞습니다. 나는 그것이 멀티 스레드 였지만 대체 기능을 실행한다고 믿게되었습니다 지금은 100 % 제 3 자 문제입니다. 어쨌든 모든 빠른 응답을 주셔서 감사합니다. 일부 여분의 코어를 사용하는 멋진 보법이 필요할 수도 있습니다. ( – Skyline

+0

가능한 경우 멋진 보법을 공유하십시오 ... 한 두 가지를 배우기에는 너무 늦지 마십시오 – Darek

0

문제는 타사 DLL이 단일 스레드 COM 모델이라는 점입니다. 나는 그것이 멀티 스레드 였다고 믿게되었다. 그러나 대체 기능을 실행함으로써 지금은 100 % 제 3 자 문제이다. 어쨌든 모든 빠른 응답 주셔서 감사합니다. 몇 가지 추가 코어를 사용해야하는 멋진 보법이 필요할 수 있습니다. 회사에 MT 버전이 있는지 확인하는 이메일을 보냈지 만 의심 스럽습니다. 다시 한번 감사드립니다.

+0

질문이 해결되면 답을 표시하십시오. – ErnieL

관련 문제