简体   繁体   English

为什么我的WCF客户端在调用引发事件的WCF服务器中的方法后超时?

[英]Why is my WCF client timing out after calling a method in the WCF server that raises an event?

I have a WCF service hosted within a Windows service. 我在Windows服务中托管了WCF服务。 There is s method in the WCF service that will raise an event that the Windows service subscribes to. WCF服务中有一种方法会引发Windows服务订阅的事件。 When the event is raised and the Windows service catches it, the Windows service calls another WCF method to send a message to all connected clients. 引发事件并且Windows服务捕获该事件时,Windows服务会调用另一个WCF方法向所有连接的客户端发送消息。 For some reason when I have all these these happen in this sequence an error is thrown: 出于某种原因,当我将所有这些发生在这个序列中时,会抛出一个错误:

This request operation sent to http://localhost:8731/Design_Time_Addresses/WCF/WCFService/ did not receive a reply within the configured timeout (00:00:29.9939996)....

Here is the relevant code from teh WCF service: 以下是来自WCF服务的相关代码:

public event EventHandler<CustomEventArgs> CustomEvent;

private static readonly List<IMessageCallback> subscribers = new List<IMessageCallback>();

public void SendMessageToClients(string msgType, string message)
{
    subscribers.ForEach(delegate(IMessageCallback callback)
    {
        if (((ICommunicationObject)callback).State == CommunicationState.Opened)
        {
            callback.OnMessageReceived(msgType, message, DateTime.Now);
        }
        else
        {
            subscribers.Remove(callback);
        }
    });
}

public bool messageHost()
{
    try
    {
        if (CustomEvent != null)
            CustomEvent(null, new CustomEventArgs());
        return true;
    }
    catch
    {
        return false;
    }
}

And the Code from the Windows service: 而Windows服务中的代码:

wcfService = new WCF.WCFService();
sHost = new ServiceHost(wcfService);
wcfService.CustomEvent += new EventHandler<WCF.CustomEventArgs>(wcfService_CustomEvent);
sHost.Open();

private void wcfService_CustomEvent(object source, WCF.CustomEventArgs e)
{
    wcfService.SendMessageToClients("log", "CLient connected!!");
    osae.AddToLog("client message"); //just writes to a log file
}

And the client just calls this: 客户端只是这样称呼:

wcfObj.messageHost();

Here is the client config: 这是客户端配置:

  <system.serviceModel>
<bindings>
  <wsDualHttpBinding>
    <binding name="WSDualHttpBinding_IWCFService" closeTimeout="00:00:10"
      openTimeout="00:00:10" receiveTimeout="00:10:00" sendTimeout="00:00:30"
      bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
      maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
      textEncoding="utf-8" useDefaultWebProxy="true">
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <reliableSession ordered="true" inactivityTimeout="00:10:00" />
      <security mode="Message">
        <message clientCredentialType="Windows" negotiateServiceCredential="true"
          algorithmSuite="Default" />
      </security>
    </binding>
  </wsDualHttpBinding>
</bindings>
<client>
  <endpoint address="http://localhost:8731/Design_Time_Addresses/WCF/WCFService/"
    binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IWCFService"
    contract="WCFService.IWCFService" name="WSDualHttpBinding_IWCFService">
    <identity>
      <dns value="localhost" />
    </identity>
  </endpoint>
</client>

And the service config: 和服务配置:

<system.serviceModel>
<services>
  <service name="WCF.WCFService" behaviorConfiguration="WCFBehavior">
    <endpoint address="" binding="wsDualHttpBinding" contract="WCF.IWCFService">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint
      address="mex"
      binding="mexHttpBinding"
      bindingConfiguration=""
      contract="IMetadataExchange"/>
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8731/Design_Time_Addresses/WCF/WCFService/" />
      </baseAddresses>
    </host>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="WCFBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>

If I remove the SendMessageToClients call from the event in the Windows service it works and just logs the 'client message' as expected. 如果我从Windows服务中的事件中删除SendMessageToClients调用它可以正常工作,只需按预期记录“客户端消息”。 Also, when the error is thrown about the timeout I can click continue and the the client continues to run and it received the message from the host. 此外,当关于超时抛出错误时,我可以单击继续,客户端继续运行,它从主机收到消息。 Why is the strange behavior happening? 为什么会发生奇怪的行为?

EDIT: Marc led me to search in the right place: http://www.codeproject.com/KB/WCF/WCF_Duplex_UI_Threads.aspx 编辑: Marc带我去正确的地方搜索: http//www.codeproject.com/KB/WCF/WCF_Duplex_UI_Threads.aspx

The symptoms here suggest to me like there is a deadlock happening, perhaps due to a sync-context (WCF respects sync-context by default). 这里的症状建议对我来说,有一个死锁发生,可能是由于同步上下文(WCF默认尊重同步上下文)。 Meaning: the outward message is waiting on access to the context, but it is itself the thing that the existing context is waiting on. 含义: 外部消息正在等待访问上下文,但它本身就是现有上下文所等待的内容。

The easiest way to investigate that would be to perform the outward message on a worker thread: 调查的最简单方法是在工作线程上执行外向消息:

ThreadPool.QueueUserWorkItem(delegate {
    wcfObj.messageHost();
});

I believe you can also configure WCF to change how it approaches sync-context, but I can't remember how... 相信您也可以配置WCF来改变它接近同步上下文的方式,但我不记得如何...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM