Приложение Winforms перестает отвечать на запросы через некоторое время при выполнении асинхронных вызовов WCF через netTcpBinding

Сценарий

Я поддерживаю/улучшаю приложение Windows Form, которое обменивается данными через службу WCF, размещенную в IIS, с использованием класса ServiceHostFactory.

Для проблемы, которую я пытаюсь решить, я имею дело с этими двумя методами в ServiceContract. ServiceContract помечен как PerCall.

    [OperationContract(IsOneWay = true)]
    void RunJob(int jobId);

    [OperationContract]
    byte[] GetUserJobs(int userID);

Пользователь отправит задание с помощью метода RunJob в стиле "сгорел и забыл". Это задание сделает вызов WCF к другой службе, вернет некоторые данные, проделает с ними множество действий и сохранит их в базе данных. Эта конкретная работа занимает примерно 62 минуты.

Пока задание находится в состоянии Выполняется, клиент асинхронно вызывает метод GetUserJobs каждые 10 секунд, чтобы проверить состояние задания и соответствующим образом обновить графический интерфейс. Клиент взаимодействует со службой WCF через netTcpBinding.

Проблема

Примерно через 1 час графический интерфейс полностью перестает отвечать на запросы. Асинхронные вызовы все еще выполняются, но завершенное событие никогда не вызывается. Мне кажется, что-то заблокировано или блокируется, и я не могу точно понять, почему это происходит. Графический интерфейс может перестать отвечать на запросы до того, как RunJob (OneWay) фактически завершится на сервере, но само задание всегда завершается, и данные сохраняются в базе данных.

Таким образом, несмотря на то, что графический интерфейс непригоден для использования, сервер все еще работает, за исключением того, что он не отвечает ни на какие вызовы WCF.

Если я отредактирую web.config на сервере, чтобы перезапустить IIS, графический интерфейс снова станет отзывчивым.

Я ни в коем случае не эксперт WCF, и я действительно изо всех сил пытаюсь найти решение этой проблемы. Я почти уверен, что это происходит из-за асинхронных вызовов, но пока не могу точно определить причину. Асинхронные вызовы закрываются в соответствии с приведенным ниже кодом.

Согласно моим журналам трассировки, я вижу следующие ошибки сразу после того, как графический интерфейс перестает отвечать на запросы:

<ExceptionType>System.ServiceModel.CommunicationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>There was an error writing to the pipe: The pipe is being closed. (232, 0xe8).</Message>

Затем для Activity http://tempuri.org/IConnectionRegister/ValidateUriRoute я увижу:

<DataItem> <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Warning"> <TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.CommunicationObjectFaulted.aspx</TraceIdentifier> <Description>Faulted System.ServiceModel.Channels.ClientFramingDuplexSessionChannel</Description> <AppDomain>/LM/W3SVC/2/ROOT/Service_mt-4-130395564562210673</AppDomain> <Source>System.ServiceModel.Channels.ClientFramingDuplexSessionChannel/56837067</Source> </TraceRecord> </DataItem>

<DataItem> <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Warning"> <TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.CommunicationObjectFaulted.aspx</TraceIdentifier> <Description>Faulted System.ServiceModel.Channels.ServiceChannel</Description> <AppDomain>/LM/W3SVC/2/ROOT/Service_mt-4-130395564562210673</AppDomain> <Source>System.ServiceModel.Channels.ServiceChannel/3537205</Source> </TraceRecord> </DataItem>

Соответствующий код/конфигурация (немного очищены)

Конфигурация привязки клиента

На данный момент я попытался установить для всех тайм-аутов «бесконечность», просто чтобы исключить какое-то странное поведение тайм-аута. Я пробовал различные настройки времени ожидания, но ничего не работает.

    <binding name="MyEndpoint" closeTimeout="infinite"
                openTimeout="infinite" receiveTimeout="infinite" sendTimeout="infinite"
                transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
                hostNameComparisonMode="StrongWildcard" listenBacklog="10"
                maxBufferPoolSize="2147483647" maxBufferSize="2147483647"
                maxConnections="100" maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
                  maxArrayLength="2147483647" maxBytesPerRead="2147483647"
                  maxNameTableCharCount="2147483647" />
          <reliableSession ordered="true" inactivityTimeout="infinite"
                  enabled="false" />
          <security mode="Transport">
            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
            <message clientCredentialType="Windows" />
          </security>
</binding>

Конфигурация привязки к серверу

      <netTcpBinding>
    <binding name="MyBinding" portSharingEnabled="true" transferMode="Buffered" closeTimeout="infinite" openTimeout="infinite" receiveTimeout="infinite" sendTimeout="infinite" maxBufferPoolSize="524288" maxBufferSize="2147483647" maxConnections="10" listenBacklog="200" maxReceivedMessageSize="2147483647">
      <security mode="Transport">
        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
        <message clientCredentialType="Windows" />
      </security>
      <reliableSession ordered="true"
             inactivityTimeout="infinite"
             enabled="false" />
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
    </binding>
<netTcpBinding>

 <serviceBehaviors>
    <behavior name="MyServiceBehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      <ServiceErrorHandler />
      <dataContractSerializer maxItemsInObjectGraph="2147483647" />          
    </behavior>
    <behavior name="">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>

Графический интерфейс делает что-то похожее на следующее для асинхронного вызова службы WCF:

 public void RefreshJobs()
 {
    //When the GUI becomes unresponsive, a lot of these log statements start piling up in the log file, until service is restarted
    Logger.GetInstance().Info("Begin RefreshJobs");
    ServiceClient svc = new ServiceClient("MyEndpoint", url);
    try
    {
        svc.GetUserJobsCompleted += new EventHandler<GetUserJobsCompletedEventArgs>(svc_GetJobsCompleted);
    }
    catch (Exception e)
    {
        throw e;
    }

    svc.GetUserJobsAsync(SomeSingleton().CurrentUser.UserID, false, svc);
    Logger.GetInstance().Info("End RefreshJobs");
}        

private void svc_GetJobsCompleted(object sender, GetUserJobsCompletedEventArgs e)
{
    Logger.GetInstance().Info("Start GetJobsCompleted");
    if (e.Result != null)
    {
        //Do Stuff to Update GUI
    }

    //Close the connection
    if (e.UserState is ServiceClient)
    {
        ((ServiceClient)e.UserState).Close();
    }
    Logger.GetInstance().Info("End GetJobsCompleted");
}

person kelsmj    schedule 18.03.2014    source источник


Ответы (1)


Проблема оказалась в перегрузке ЦП, из-за чего Smsvchost.exe перестал отвечать на запросы.

Исправление от Microsoft доступно.

person kelsmj    schedule 01.04.2014