WCF通道工厂和打开超时

6

在客户端中,我试图将OpenTimeout属性更改为5秒钟,以连接到WCF,但它不起作用...这是我创建通道的方式:

NetTcpBinding bind = new NetTcpBinding(SecurityMode.None);
bind.OpenTimeout = new TimeSpan(0, 0, 5);
var channel = new ChannelFactory<IService>(bind, new EndpointAddress(myAddr)); 
channel.CreateChannel();

在此之后,我调用了该方法,但如果服务器停机,它需要21秒才能响应,而不是我在OpenTimeout上更改的5秒。我有什么遗漏的吗?
谢谢。

1
如果您发布代码、XML或数据示例,请在文本编辑器中突出显示这些行,并单击编辑器工具栏上的“代码示例”按钮({})以使其格式化和语法高亮! - marc_s
抱歉 @marc_s,我真的忘了。 - Alexandre
@Alexandre,你找到解决这个问题的方法了吗?因为我也遇到了同样的问题。 - Carlos487
4个回答

5
我用以下方法解决了这个问题。它似乎有效。
    protected TServiceContract CreateChannel()
    {
        TServiceContract channel = factory.CreateChannel();

        var ar = ((IChannel)channel).BeginOpen( null, null );

        if( !ar.AsyncWaitHandle.WaitOne( factory.Endpoint.Binding.OpenTimeout, true ) )
        {
            throw new TimeoutException( "Service is not available" );
        }

        ((IChannel)channel).EndOpen( ar );

        return channel;
    }

如果你说的是关于并发通道创建的问题 - 是的。我没有遇到任何问题。 - Mimas

1
我找到的解决方案是在调用方法之前检查wcf服务器是否启动,具体方法如下:
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.ReceiveTimeout = sock.SendTimeout = 500;
IAsyncResult res = sock.BeginConnect(ip, port, null, null);
bool success = res.AsyncWaitHandle.WaitOne(500, true);

这个解决方案的问题是并发访问...有时如果被占用,套接字会返回false。 - Alexandre

1

第一次调用服务的方法也会打开通道。这被称为自动打开,不建议使用。相反,您应该显式地调用它:

channel.Open();
channel.RetrieveFoobars();

然而,问题仍然存在:channel.Open()不尊重绑定的OpenTimeout,而是在大约21秒后抛出一个EndpointNotFoundException异常。我猜这是WCF CommunicationObject的一个bug。
使用上述代码设置((IContextChannel)channel).OperationTimeout、bind.SendTimeout或bind.OpenTimeout并没有帮助(如其他地方所建议的)。
基于此VB代码(请看这里),我找到了解决方案:使用允许您指定等待时间以在取消前使用异步方法。
private void CloseChannel(ICommunicationObject channel){
  try {
    channel.Close();
  } catch {
    channel.Abort();
  }
}

private void OpenChannel(ICommunicationObject channel, TimeSpan timeout) {
  var ar = channel.BeginOpen(null, null);
  if (!ar.AsyncWaitHandle.WaitOne(timeout, true)) {
    CloseChannel(channel);
    throw new EndpointNotFoundException();
  }
  channel.EndOpen(ar);
}

您仍需先将绑定的OpenTimeout设置至少为50毫秒,否则BeginOpen会抛出TimeoutException。

bind.OpenTimeout = TimeSpan.FromMilliseconds(100d)

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接