【问题标题】:Do I need to close a .NET service reference client when I'm done using it使用完毕后是否需要关闭 .NET 服务参考客户端
【发布时间】:2011-03-15 20:50:41
【问题描述】:

我正在尝试确定在您使用完毕后是否需要关闭 .net 服务参考客户端。我在网上遇到的几乎所有示例似乎都没有,但是生成的客户端实现了 IDisposable 并且由于它确实打开了与服务的连接,所以我的直觉告诉我,当你需要关闭该连接时已经完成了。

这是我从http://msdn.microsoft.com/en-us/library/bb386386(v=VS.90).aspx 提取的代码示例:

private void button1_Click(System.Object sender, System.EventArgs e)
{
    ServiceReference1.Service1Client client = new 
        ServiceReference1.Service1Client();
    string returnString;

    returnString = client.GetData(textBox1.Text);
    label1.Text = returnString;
}

我认为您至少应该在此方法的末尾调用 client.Close(),并且最好将第一行包含在 using 语句中。我只是想就此获得一些反馈,以了解最佳做法是什么。

【问题讨论】:

    标签: c# .net wcf web-services idisposable


    【解决方案1】:

    是的,你这样做,但这样做时你需要非常小心。在关闭任何实现 ICommunicationObject 的东西时,如果通道上出现错误或故障,可能会导致对象的处置花费过多的时间。

    因此,规定您调用Close method,然后在IDisposable 上调用Dispose 方法,对某些异常类型使用一些捕获并调用Abort,然后最后调用@987654329 @。

    您可以将此逻辑封装在IDisposable 实现中,您可以在using 语句中使用它。

    这里的关键是创建一个实现IDisposable 的令牌,然后在该实现中调用Close,捕获相关异常,调用Abort(如有必要),然后调用Dispose

    这是作为一个扩展方法实现的,它在其上返回一个 IDisposable,这反过来又允许您在 using 语句中使用它。

    【讨论】:

      【解决方案2】:

      最佳做法是,如果该类实现 IDisposable,则在 finally 子句中调用 Dispose(),或使用 using () { } 包装它

      编辑
      在下面的@casperOne 评论之后,似乎应该更加谨慎地对待 WCF 客户端。我不知道这一点,并且对此有点不安,到目前为止 using() 对我很有帮助。

      【讨论】:

      • 我很困惑为什么我发现的所有 msdn 示例都没有这样做。他们不想在他们提供的示例中说明最佳实践吗?
      • 您希望如此,但我认为这些示例通常展示了有关其他类的特定点。我见过 Crypto 样本对文件进行编码,甚至不会尝试/捕获 FileStream 实例,我们永远不会这样做,对吗? (!)
      • -1:实现 ICommunicationObject 的事物不能简单地调用 Dispose,原因在此处指出:caspershouse.com/post/… 和此处:msdn.microsoft.com/en-us/library/aa355056.aspx - 您必须中止面对某些异常和然后调用 Dispose。
      • +1:这应该被视为 ICommunicationObject 实现中的错误。我们是从什么时候开始忍受意想不到的 using 语句结果的?
      • @slf:自 2006 年 WCF 发布以来,我们已经忍受了它。这是设计缺陷,而不是错误。
      【解决方案3】:

      最好的办法是查看为Dispose() 生成的客户端代码,看看它是否真的在处理任何东西,比如HTTP 连接或其他东西。

      一方面,它实现的接口可能只是继承自IDisposable,因为某些客户端可能需要处理某些东西,即使那个特定的客户端不需要。这类似于MemoryStream,一个实现IDisposable 的类,因为所有Streams 都这样做,但实际上并不处理任何非托管资源。

      另一方面,使用using 永远不会有什么坏处,即使Dispose() 是一个空方法。 MS 示例实际上非常糟糕关于不使用using,即使他们应该使用(例如here),所以不要把他们的例子当作你不需要的好证据。

      【讨论】:

      • 我个人宁愿不对 3rd 方程序集进行逆向工程,看看我是否可以不调用 Dispose - 这不会带来风险,在组件或框架的下一个版本中,你需要处理并留下一个代码库,将非托管资源清理留给 GC?
      • -1:针对实现而不是根据合同进行编码总是是个坏主意。如果该类型实现 IDisposable,则应始终调用 Dispose。不这样做的唯一原因是当确定您有特殊情况并且这样做会损害您的系统并需要解决方法时。此外,在您的 MemoryStream 示例中,您应该调用 Dispose,因为不能保证将来不会将非托管内存用作后备存储,因此您的代码不会是未来的证明如果这方面发生了变化。
      • @neil,然后一定要调用 Dispose();我建议它是因为你有实际的代码。 @casperOne,对接口进行编码通常是一个好主意,但作为一条不灵活的规则,它忽略了类型系统并不完美的事实。例如,非托管内存块是红鲱鱼:我可以实现 IList 以使用非托管内存,但如果消费者编码到 IList 接口,他甚至不知道他可以调用 Dispose()。
      • -1:从不对像 WCF 这样复杂的东西进行逆向工程,然后依赖它。特别是,由于生成的客户端代码不是实际工作的内容 - 它是基类,它是 WCF 的一部分。
      • 您是在暗示阅读您生成的代码是对所有 WCF 的逆向工程?没那么多。此外,已经非常强大的“总是”和“从不”的斜体使用严重夸大了你的情况。 OP 询问他是否需要对他的对象调用 Close,答案是——无论你提出多少工程准则——这取决于代码的内容。
      猜你喜欢
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-07
      • 1970-01-01
      • 2011-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多