2014-04-01 64 views
4

我正在設計一個WPF應用程序使用的WCF服務。 該服務將由50個客戶端使用並託管在多核服務器上。這就是爲什麼我希望它是多線程的。WCF服務不是多線程的

這是我宣佈它:

[ServiceContract(
    SessionMode = SessionMode.Required, 
    Namespace = Constants.NameSpace, 
    CallbackContract = typeof (ISaphirServiceCallback))] 
public interface ISaphirService 


[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, 
       InstanceContextMode=InstanceContextMode.PerSession)] 
public partial class SaphirService : ISaphirService 

而服務器端配置:

<system.serviceModel> 
    <bindings> 
     <netTcpBinding> 
     <binding name="NewBinding0" receiveTimeout="00:59:00" sendTimeout="00:59:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="20000000"> 
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
      <reliableSession ordered="true" inactivityTimeout="00:30:00" enabled="true"/> 
      <security mode="Message"> 
      <message clientCredentialType="UserName" /> 
      </security> 
     </binding> 
     </netTcpBinding> 

     <customBinding> 
     <binding name="ServicePECB2ServiceBinding"> 
      <textMessageEncoding messageVersion="Soap12WSAddressing10" /> 
      <httpsTransport /> 
     </binding> 
     </customBinding> 
    </bindings> 
    <client> 
     <endpoint address="https://qualiflps.services-ps.ameli.fr/lps" binding="customBinding" bindingConfiguration="ServicePECB2ServiceBinding" contract="ServiceReference1.ServicePECB2Service" name="ServicePECB2Service" /> 
    </client> 

    <behaviors> 
     <serviceBehaviors> 
     <behavior name="NewBehavior0"> 
      <serviceThrottling maxConcurrentCalls="50" maxConcurrentSessions="50" maxConcurrentInstances="50"/> 
      <serviceAuthorization serviceAuthorizationManagerType="Service.Authorizations.AuthorizationPolicy, Service"> 
      <authorizationPolicies> 
       <add policyType="Service.Authorizations.AuthorizationPolicy, Service" /> 
      </authorizationPolicies> 
      </serviceAuthorization> 
      <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:80/Service" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
      <serviceCredentials> 
      <serviceCertificate storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName" findValue="*****" /> 
      <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Service.Authorizations.CustomValidator, Service" /> 
      </serviceCredentials> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <services> 
     <service behaviorConfiguration="NewBehavior0" name="Service.Services.SaphirService"> 
     <endpoint address="basic" binding="netTcpBinding" bindingConfiguration="NewBinding0" contract="ServiceInterfaces.IServices.ISaphirService"> 
      <identity> 
      <dns value="*****" /> 
      </identity> 
     </endpoint> 
     </service> 
    </services> 
    </system.serviceModel> 

這裏是客戶端配置:

<system.serviceModel> 
    <bindings> 
     <netTcpBinding> 
     <binding name="NetTcpBinding_ISaphirService" receiveTimeout="00:30:00" sendTimeout="00:05:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="20000000"> 
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
      <reliableSession ordered="true" inactivityTimeout="00:30:00" enabled="true"/> 
      <security mode="Message"> 
      <message clientCredentialType="UserName" /> 
      </security> 
     </binding> 
     </netTcpBinding> 
    </bindings> 
    <client> 
     <endpoint address="http://****:4224/service/basic" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ISaphirService" contract="ISaphirService" name="NetTcpBinding_ISaphirService" behaviorConfiguration="CustomBehavior"> 
     <identity> 
      <certificate encodedValue="****" /> 
     </identity> 
     </endpoint> 
    </client> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="CustomBehavior"> 
      <clientCredentials> 
      <serviceCertificate> 
       <authentication certificateValidationMode="PeerOrChainTrust" /> 
      </serviceCertificate> 
      </clientCredentials> 
     </behavior> 
     </endpointBehaviors> 
    </behaviors> 
    </system.serviceModel> 

的事情是,每個請求都在同一個線程上處理。 我在互聯網上查了很多,但一切似乎對我來說都很好......

你們有什麼想法嗎?

謝謝!

+3

你是怎麼檢查的?如果有50個客戶端執行服務,並且您進入睡眠狀態,他們是否會一個接一個地等待處理? – nvoigt

+2

多少次請求,多長時間以及多長時間? –

+0

我檢查了兩個客戶端。首先清楚地看到客戶端#2的請求#1正在等待來自客戶端#1的第一個請求,並且還有一些Console.Write(ManagedThreadId) –

回答

7

當打開ServiceHost WCF捕獲當前SynchronizationContext,並將其用於所有呼叫。 WPF的同步上下文會每次調用Dispatcher隊列,最終在UI線程上執行。

你有兩個選擇:

  • 開始在不同的線程不具有同步方面的服務。這具有額外的優點,即不阻塞等待服務加載的UI線程。例如,你可以使用:

    Task.Run(() => serviceHost.Open()); 
    
  • 指定的服務不應該使用同步上下文:

    [ServiceBehavior(UseSynchronizationContext = false)] 
    

請注意,如果您修改服務方法UI對象,你可能需要將它們自己分發回UI線程。

+0

太棒了!一行代碼,一切都很順利:D非常感謝! –

0

如果您希望您的服務保持來自同一客戶端的呼叫之間的某種狀態,那麼值得一提的是InstanceContextMode=InstanceContextMode.PerSession。否則,您可以使用InstanceContextMode=InstanceContextMode.PerCall

+0

我確實需要會話,我正在使用服務中的很多Push請求 –

+0

我不確定模擬50個客戶端調用時所需的驗證級別。但是,ServiceThrottling可能是最好的開始。你也可以看看這篇文章http://www.codeproject.com/Articles/33362/WCF-Throttling – Nair

+0

我覺得我的配置對於ServiceThrottling是好的,不是嗎? –