Почему у моего клиента WCF истекло время ожидания после вызова метода на сервере WCF, который вызывает событие? - PullRequest
4 голосов
/ 23 сентября 2011

У меня есть служба WCF, размещенная в службе Windows. В службе WCF есть метод s, который вызывает событие, на которое подписывается служба Windows. Когда событие возникает и служба Windows перехватывает его, служба Windows вызывает другой метод WCF, чтобы отправить сообщение всем подключенным клиентам. По какой-то причине, когда у меня все это происходит, в этой последовательности выдается ошибка:

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)....

Вот соответствующий код службы 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;
    }
}

И Код из службы 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
}

И клиент просто называет это:

wcfObj.messageHost();

Вот клиентская конфигурация:

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

И сервисный конфиг:

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

Если я удаляю вызов SendMessageToClients из события в службе Windows, он работает и просто регистрирует «клиентское сообщение», как и ожидалось. Кроме того, когда выдается ошибка о тайм-ауте, я могу нажать продолжить, и клиент продолжает работать, и он получил сообщение от хоста. Почему происходит странное поведение?

EDIT: Марк привел меня к поиску в нужном месте: http://www.codeproject.com/KB/WCF/WCF_Duplex_UI_Threads.aspx

1 Ответ

3 голосов
/ 23 сентября 2011

Симптомы здесь подсказывают мне , что возникла тупиковая ситуация, возможно, из-за синхронизирующего контекста (WCF по умолчанию учитывает синхронизирующий контекст). Значение: сообщение outward ожидает доступа к контексту, но само означает, что существующий контекст ожидает.

Самый простой способ выяснить это - выполнить исходящее сообщение в рабочем потоке:

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

Я верю Вы также можете настроить WCF, чтобы изменить подход к контексту синхронизации, но я не могу вспомнить, как ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...