有效关闭WCF 4通道的正确方法

13

我正在使用以下方式关闭WCF 4通道。这是正确的做法吗?

using (IService channel 
    = CustomChannelFactory<IService>.CreateConfigurationChannel())
{
    channel.Open();

    //do stuff
}// channels disposes off??
2个回答

26

这曾经是WCF“早期”释放客户端代理常用的方法。

然而,事情已经有所改变。原来IClientChannel<T>.Dispose()的实现只会调用IClientChannel<T>.Close()方法,在某些情况下,例如底层通道未打开或无法及时关闭等情况下,这可能会引发异常。

因此,在catch块中调用Close()不是一个好主意,因为在出现异常的情况下,这可能会留下一些未释放的资源。

现在推荐的新方法是,在catch块中调用IClientChannel<T>.Abort(),以防止Close()操作失败。以下是一个示例:

try
{
    channel.DoSomething();
    channel.Close();
}
catch
{
    channel.Abort();
    throw;
}

更新:

这里提供了一篇 MSDN 文章的参考,该文章描述了该建议。


我真的需要关闭通道吗?我在考虑将其保持打开状态,下次使用时检查factory.State != CommunicationState.Opened(在我的情况下是管道工厂),如果为真,则重新创建通道。 - Valentin
2
@Valentin 简短的回答是是的,当不再需要WCF通道时,您应该显式地释放它。打开的WCF通道持有一些较低级别的资源,例如TCP套接字或HTTP连接。如果您通过将其留在垃圾收集器的非确定性手中来延迟释放这些资源,则可能会遇到资源变得稀缺的情况,这将使创建新通道变得不可能。 - Enrico Campidoglio
你有没有关于描述这种推荐变更的文档参考? - Macke

9

虽然不是专门针对渠道的,但你可以执行以下操作:

ChannelFactory<IMyService> channelFactory = null;
try
{
    channelFactory =
        new ChannelFactory<IMyService>();
    channelFactory.Open();

    // Do work...

    channelFactory.Close();
}
catch (CommunicationException)
{
    if (channelFactory != null)
    {
        channelFactory.Abort();
    }
}
catch (TimeoutException)
{
    if (channelFactory != null)
    {
        channelFactory.Abort();
    }
}
catch (Exception)
{
    if (channelFactory != null)
    {
        channelFactory.Abort();
    }
    throw;
}

5
这个回答有点偏离主题:它提供了ChannelFactory的使用模式,而原问题涉及通道。虽然关闭工厂确实会关闭其创建的所有通道(我相信),但更常见的模式是保持ChannelFactory开放以便高效地创建多个通道。在保持工厂处于打开状态的同时,应单独关闭每个通道以进行工作。 - Elroy Flynn
没错 - 谢谢你指出来。已经调整了帖子以反映该问题。 - tom redfern

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