【问题标题】:WCF Duplex Service Channel CloseWCF 双工服务通道关闭
【发布时间】:2014-06-23 14:28:07
【问题描述】:

我有一个基于 WCF Duplex 服务的应用程序。当用户“重新启动”应用程序所做的工作时,我遇到了问题......在后台,客户端关闭了与 WCF 服务的连接并创建了另一个。服务合同是这样定义的......

[ServiceContract(Namespace="net.tcp://namespace.MyService",
    SessionMode=SessionMode.Required,
    CallbackContract=typeof(IServiceCallback))]
public interface IMyService
{
    [OperationContract(IsOneWay=true)]
    void DoWork();
}


public interface IServiceCallback
{
    [OperationContract(IsOneWay=true)]
    void SendMessage(string message);
}

实现定义为:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single,
    InstanceContextMode = InstanceContextMode.PerSession,
    UseSynchronizationContext = false,
    IncludeExceptionDetailInFaults = true)]
public class MyService : IMyService
{
    public void DoWork()
    {
        var callback = OperationContext.Current.GetCallbackChannel<IServiceCallback>();
        callback.SendMessage("Hello, world.");
    }
}

客户端的配置如下:

  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="net.tcp" receiveTimeout="02:00:00" sendTimeout="02:00:00" maxReceivedMessageSize="2147483647">
          <security mode="None"/>
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="net.tcp://localhost:8000/MyService/MyService"
          binding="netTcpBinding" bindingConfiguration="net.tcp" contract="ExternalServiceReference.IMyService">
      </endpoint>
    </client>
  </system.serviceModel>

服务配置:

<system.serviceModel>
<behaviors>
  <serviceBehaviors>
    <behavior name="serviceBehaviour">
      <serviceMetadata />
    </behavior>
  </serviceBehaviors>
</behaviors>
<bindings>
  <netTcpBinding>
    <binding name="netTcp" sendTimeout="01:00:00" receiveTimeout="01:00:00" >
      <security mode="None">
      </security>
    </binding>
  </netTcpBinding>
</bindings>
<services>
  <service behaviorConfiguration="serviceBehaviour" name="MyService.MyService">
    <endpoint address="MyService" binding="netTcpBinding" bindingConfiguration="netTcp" name="net.tcp" contract="MyService.IMyService" />
    <endpoint binding="mexTcpBinding" bindingConfiguration="" name="net.tcp" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8000/MyService" />
      </baseAddresses>
    </host>
  </service>
</services>

在客户端的构造器中:

var callback = new CallbackImplementation();
_context = new InstanceContext(callback);
_proxy = new MyServiceProxy(_context);

在建立新连接之前,我正在尝试以下操作:

        try
        {
            if (_context != null)
            {
                _context.ReleaseServiceInstance();
                _context.Close();                    
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
            if (_context != null)
            {
                _context.Abort();
            }
        }

我看到的问题是 _context.Close() 调用总是超时并引发异常。尽管我随后中止了频道,但这对我来说感觉不对,我相信这是我的应用程序冻结的原因。有人知道为什么 Close() 调用失败了吗?

编辑:我之前错过了一些可能相关的回调实现。它看起来像这样:

[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Single, 
    UseSynchronizationContext = false, 
    IncludeExceptionDetailInFaults = true)]
public class CallbackImplementation : IServiceCallback
{
    public void SendMessage(string message)
    {
        // Do something with the message
    }
}

异常消息是“ServiceHost 关闭操作在 00:00:30 后超时。这可能是因为客户端未能在要求的时间内关闭会话通道。分配给此操作的时间可能是更长的超时时间。”。没有内在的例外。

谢谢

【问题讨论】:

  • 尝试添加一个OnClose 事件处理程序。查看事件是否在 callback 服务器端触发。
  • 谢谢,我刚试过:Closing 和 Closed 事件都在触发。
  • 但是服务仍然超时?您是否尝试在绑定上设置CloseTimeout
  • 是的,我已经在两端设置了 closeTimeout 并且发生了同样的问题。
  • 能否请您发布例外情况?此外,应用程序响应性的快速解决方案是这样做:Task.StartNew(()=&gt;{_context.Close();});

标签: c# wcf


【解决方案1】:

我没有立即发现问题,但我经常发现在客户端和服务器上运行跟踪并检查结果通常会为我指明解决方案。将其放入您的 .config 文件(客户端和服务器)中,确保路径指向存在的文件夹。运行您的应用程序,遇到故障,然后关闭一切并运行 SvcTraceViewer.exe 以读取结果。

<system.diagnostics>
    <sources>
      <source name="System.ServiceModel" switchValue="Information,ActivityTracing"
        propagateActivity="true">
        <listeners>
          <add name="xml" />
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="xml" />
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add initializeData="C:\logs\TracingAndLogging-service.svclog" type="System.Diagnostics.XmlWriterTraceListener"
        name="xml" />
    </sharedListeners>
    <trace autoflush="true" />
</system.diagnostics>

【讨论】:

    【解决方案2】:

    您是否尝试过 receiveTimeout="infinite",看看您是否仍然收到错误。您可能只是发现创建错误的不是超时。您是否考虑过创建一个基客户端类来自动保持连接直到物理关闭?

    【讨论】:

      【解决方案3】:

      猜测可能是使用ConcurrencyMode.Single造成的死锁。

      可能发生的情况是服务器在处理原始请求时尝试回调客户端(反之亦然)。所以服务器试图回调客户端,但客户端阻塞,因为它仍在等待服务器的响应。嘿 presto,死锁,最终超时。

      http://msdn.microsoft.com/en-us/library/system.servicemodel.concurrencymode.aspx

      【讨论】:

        【解决方案4】:

        问题不仅在于并发,还在于绑定类型。

        确保服务和回调的并发模式是朝着正确方向迈出的一步。但是将绑定从 netTcpBinding 更改为 wsDualHttpBinding 终于解决了问题

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多