繁体   English   中英

WCF双工服务频道关闭

[英]WCF Duplex Service Channel Close

我有一个基于WCF双工服务的应用程序。 当用户“重新启动”应用程序所做的工作时,我遇到了问题......客户端关闭了与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之后超时。这可能是因为客户端未能在所需时间内关闭会话通道。分配给此操作的时间可能是较长超时的一部分“。 没有内在的例外。

谢谢

我没有立即看到问题,但我经常发现在客户端和服务器上运行跟踪并检查结果通常会指向我的解决方案。 将它放在.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>

你试过receiveTimeout =“无限”,看看你是否仍然收到错误。 您可能只是发现创建错误的超时不是。 您是否考虑过创建一个基本客户端类,它可以自动保持连接活动直到物理关闭?

猜测,它可能是使用ConcurrencyMode.Single引起的死锁。

可能发生的是服务器在处理原始请求时尝试回调客户端(反之亦然)。 因此服务器正在尝试回调客户端,但客户端正在阻塞,因为它仍在等待来自服务器的响应。 嘿presto,僵局,最终超时。

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

问题不仅是并发性,还有绑定类型。

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

暂无
暂无

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

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