【问题标题】:How important is to call dispose on a WCF ChannelFactory<T> and T channel object right after usage?使用后立即在 WCF ChannelFactory<T> 和 T 通道对象上调用 dispose 有多重要?
【发布时间】:2015-10-17 07:20:18
【问题描述】:

开发人员喜欢编写尽可能简短的代码。我们在 C# 中调用 WCF 服务,并想知道以下直觉是对还是错。 使用ChannelFactory 代码的一种方式是:

var factory = new ChannelFactory<IService>("Endpoint");
var client = factory.CreateChannel();

client.DoSomething();

((IClientChannel)client).Close();
factory.Close();

其他方式(更简洁一些)是使用包装器对象(用于工厂和通道),它实现了IDisposable,其中同时配置并用于 using 块:

using (ServiceWrapper<IService> svcWrapper = new ServiceWrapper<IService>("Endpoint")) {
    svcWrapper.Channel.DoSomething();
}

在这里,必须调用包装器的属性对开发人员来说可能有点烦人。基本上也可以是:

using (ServiceWrapper<IService> svcWrapper = new ServiceWrapper<IService>("Endpoint")) {
    IService client = svcWrapper.Channel;
    client.DoSomething();
}

(我还发现this MSDN article说using块可以隐藏异常)

开发人员可能更喜欢的是:

 IService client = new ServiceWrapper<IService>("Endpoint").Channel;
 client.DoSomething();

摘自《C# 5.0 in a Nutshell》一书:

一种流行的模式是让终结器调用 Dispose。这使得 感知何时清理不紧急并通过调用 Dispose 加速清理 与其说是必需品,不如说是一种优化。

如果我将其添加到我的 ServiceWrapper(C# Finalize/Dispose 模式):

public void Dispose() {
    Dispose(true);
    GC.SuppressFinalize(this);
}

~ServiceWrapper() {
    Dispose(false);
}

那么 GC 最终会调用 Dispose 并做需要做的事情。即:

public void Dispose(bool disposing) {
    if (disposing) {
        if (_channel != null) {
            ((IClientChannel)_channel).Close();
        }
        if (_factory != null) {
            _factory.Close();
        }

        _channel = null;
        _factory = null;
    }
}

我觉得这不是一个与 WCF ChannelFactory&lt;T&gt;T 通道一起使用的好习惯,但我没有一个很好的解释,这会吓跑开发人员使用它。能解释一下吗?

我不能说它不起作用,我试过了,它工作正常。我看不到任何明显的性能差异或类似... 除了“你不知道终结器何时被调用”之外,我无法给出其他解释。 谢谢!

【问题讨论】:

    标签: c# .net wcf oop


    【解决方案1】:

    好吧,Dispose 方法所做的唯一事情就是显式关闭连接。就这些。您可以在reference source 中亲自查看。另外,ClientBase&lt;T&gt;,连接的基类也是如此。

    也就是说,如果您自己致电Close,则目前根本不需要致电Dispose,尽管我认为您确实应该Dispose,以防万一。此外,这对于发生可能阻止调用 Close 的错误也是一种故障保护。

    【讨论】:

    • 谢谢!这清除了一些迷雾。不手动调用Close 并让终结器来做会有很大的危险吗?
    • 除了保持应该关闭的连接并弄乱服务器和客户端上的内存之外?不,这是尽快关闭它的好理由。
    • 我明白了。无论如何使用Dispose 方法(通过调用或using 块)将是最安全的方法。谢谢您的帮助!仍然欢迎任何澄清。
    • @DDan Dispose 将调用 close 可以抛出。您应该使用 try{..}catch{..} 模式按照问题中的链接进行发布。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 2013-01-10
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多