在通过netTcpBinding进行异步WCF调用一段时间后,Winforms App无响应

时间:2014-03-18 16:14:03

标签: winforms wcf asynchronous hang net.tcp

方案

我支持/增强了一个Windows窗体应用程序,它通过使用ServiceHostFactory类在IIS中托管的WCF服务进行通信。

对于我想解决的问题,我正在处理ServiceContract中的这两个方法。 ServiceContract标记为PerCall。

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

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

用户将通过 RunJob 方法以火灾和忘记的方式提交作业。这个工作将对另一个服务进行WCF调用,获取一些数据,用它做很多事情并将其存储在数据库中。这项特殊工作大约需要62分钟才能完成。

当作业处于Running状态时,客户端每10秒异步调用 GetUserJobs 方法来检查作业状态并相应地更新GUI。客户端通过netTcpBinding与WCF服务进行通信。

问题

在1小时左右,GUI变得完全没有响应。仍在进行异步调用,但永远不会调用已完成的事件。在我看来,某些东西已陷入僵局或阻塞,我无法确切地知道为什么会发生这种情况。在RunJob(OneWay)实际在服务器上完成之前,GUI可能开始变得无法响应,但是作业本身总是完成并且数据被保存到数据库中。

因此即使GUI不可用,服务器仍然可以工作,除非它不响应任何WCF调用。

如果我在服务器上编辑web.config以回收IIS,则GUI会再次响应。

我绝不是WCF专家,我真的很想找到解决这个问题的方法。由于异步调用,我很确定它正在发生,但我还无法查明确切的原因。根据以下代码,异步调用将被关闭。

根据我的跟踪日志,当GUI无响应时,我看到以下错误:

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

然后,对于活动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>

GUI执行类似于以下操作以异步调用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");
}

1 个答案:

答案 0 :(得分:0)

问题最终导致CPU过载,导致Smsvchost.exe停止响应。

Microsoft的修复程序为available