WCF服务不是多线程的

时间:2014-04-01 08:44:03

标签: c# multithreading web-services wcf

我正在设计WPF应用程序使用的WCF服务。 该服务将由50个客户端使用并托管在多核服务器上。这就是我希望它成为多线程的原因。

这是我宣布的方式:

[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>

问题是,每个请求都在同一个线程上处理。 我在网上查了很多但是一切对我来说都很好......

你们有什么想法吗?

谢谢!

2 个答案:

答案 0 :(得分:7)

打开ServiceHost WCF会捕获当前SynchronizationContext,并将其用于所有呼叫。 WPF的同步上下文将每次调用发送到Dispatcher队列,最终在UI线程上执行。

您有两种选择:

  • 在没有同步上下文的其他线程上启动该服务。这具有不阻止等待加载服务的UI线程的额外优点。例如,您可以使用:

    Task.Run(() => serviceHost.Open());
    
  • 指定服务不应使用同步上下文:

    [ServiceBehavior(UseSynchronizationContext = false)]
    

请注意,如果您在服务方法中修改UI对象,则可能需要自己将它们分发回UI线程。

答案 1 :(得分:0)

如果您希望您的服务在来自同一客户端的呼叫之间保持某种状态,则值得一提InstanceContextMode=InstanceContextMode.PerSession。否则,您可以使用InstanceContextMode=InstanceContextMode.PerCall

相关问题