0

最近学习了如何使用Microsoft.VisualBasic.FileIO.TextFieldParser来解析文本输入。在给我的示例中,TextFieldParser使用关键字调用using

using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(new StringReader(str)))

虽然经过一些 进一步的 研究,我注意到使用using关键字 for的做法TextFieldParser并不普遍。

据我了解,.NetFramework 既有托管资源,也有非托管资源。当我们使用非托管资源时,我们应该担心内存泄漏,因此我们应该处理我们使用的非托管资源。一种最好的方法是把它们放在using上下文中。

所有这些都促使我在脑海中产生两个问题,一个是特殊的,一个是一般的。以下是我的问题:

  1. 特别是: TextFieldParser 实际上是托管的还是非托管的?
  2. 一般:是否有明确的方法让我们知道资源是受管理的还是不受管理的(例如查看X类中的事物等,或者甚至从MSDN中检查某些内容 - 如果应该检查的话 - 就可以了)。在我短暂的编程经验中,有人告诉我一些指导,例如 (i) 大多数.Net类是托管的,(ii) System.Drawing 类有一些非托管资源,(iii) 提防所有数据库、网络和 COM 类,因为它们通常是不受管理的,等等......而且我一直添加到现在的列表还在继续。但我想知道是否有任何明确的方法可以知道这一点?

如果更有经验的人能帮助我在这个问题上进一步指导我,我将不胜感激。

4

2 回答 2

3

你错过了重点。每当任何类实现时IDisposable,您都应该在完成后调用Dispose它。

类是否使用非托管资源是类内部的,您根本不应该关心它。每个使用非托管资源的类还应该有一个终结器,如果您没有显式处置该类,则该终结器可以清除这些非托管资源。Dispose只是允许您以更确定和立即的方式清理其资源(托管和非托管,尽管这并不一定意味着立即释放内存)。例如,Disposeing aFileStream将立即释放文件句柄,而如果您不这样做Dispose(或Close),文件将被打开,直到下一次收集和完成。

编辑:

为了说明Dispose清理托管资源也可能是必要的,我们只需要查看事件处理程序。特别是,当您订阅一个生命周期比您更长的类的事件时:

var control = new MyHelperControl();
MyParentForm.Click += control.DoSomething();

现在,即使control超出范围,只要MyParentForm它仍然被事件处理程序引用,它就会一直存在。当父级与整个应用程序具有相同的生命周期时,同样的问题会变得荒谬——这可能是一个巨大的内存泄漏。一个示例是在应用程序的主窗体或静态事件上注册事件处理程序。

中可能还会发生其他事情Dispose。例如,再次使用 Windows 窗体,当您调用Disposea时Control,会发生很多事情:

  • 释放所有非托管资源。由于 Winforms 控件在一定程度上是原生控件的包装器,因此这通常需要大量资源——控件本身、任何钢笔、画笔、图像……所有这些都是原生资源。如果您忘记 a ,它们也会被释放Dispose,因为它们都有终结器,但这可能需要更多时间 - 当您创建和销毁大量这些对象时尤其痛苦。例如,GDI+ 对象句柄的供应有限,如果你用完了,你得到OutOfMemoryException然后你就出局了。
  • 处置所有子控件。
  • 删除任何上下文菜单处理程序(请记住,上下文菜单是一个单独的组件,仅链接到另一个控件)。
  • 删除任何数据绑定。
  • 从父容器中移除自身(如果有)。
  • 如果控件是具有自己的消息循环的窗口,则终止消息循环。

有趣的是,非托管资源最不重要,真的——它们总是有一个终结器。托管资源比较棘手,因为您或多或少地被禁止在终结器中处理托管引用(因为它们可能已经被释放,或者它们可能正在被释放,或者它们可能在中间开始被释放你的终结器......这很复杂)。所以MyParentForm.Click -= this.OnClick;在你的终结器中这样做并不是一件好事 - 更不用说它需要你让每个这样的类都可以终结,这并不是完全免费的,特别是当你期望终结器实际运行时(当你做一个Dispose, GC 被警告此实例不再需要终结)。

于 2016-01-05T10:02:32.410 回答
1

任何实现 IDisposable 接口的类的使用都应该包含在 using (...) {} 中,或者在适当的地方很好地处理。

于 2016-01-05T10:02:11.447 回答