我们如何区分C#中的托管和非托管资源? TextFieldParser是否未受管理?

时间:2016-01-05 09:59:11

标签: c# .net unmanaged managed textfieldparser

recently learned如何使用Microsoft.VisualBasic.FileIO.TextFieldParser来解析文本输入。在给我的示例中,使用关键字TextFieldParser

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

虽然在some further researches之后,我注意到using使用TextFieldParser关键字的做法并不普遍。

据我所知,.Net Framework同时拥有托管和非托管资源。当我们使用非托管资源时,我们应该worry about内存泄漏,因此我们应该处理我们使用的非托管资源。最好的方法是将它们放在using上下文中。

所有这些让我想起了两个问题,一个是特别的,一个是一般的。以下是我的问题:

  1. 特定:TextFieldParser实际上是托管还是非托管?
  2. 概述:我们是否有明确的方式来了解资源是管理还是非管理(例如查看课程中的X内容,或类似内容,甚至是检查来自MSDN的内容 - 如果有任何检查 - 将会这样做。在我的简短编程经验中,我被告知了一些指导,例如(i)大多数.Net类被管理,(ii)System.Drawing类有一些非托管资源,(iii)要小心所有数据库,网络,和COM类,因为它们通常是不受管理的等等......而且这个列表一直在继续添加到现在。但我想知道是否有任何明确的方式来了解这一点?
  3. 如果经验丰富的人有助于进一步指导我解决这个问题,我将非常感激。

2 个答案:

答案 0 :(得分:2)

你错过了这一点。每当任何课程实施IDisposable时,您应该在完成任务后致电Dispose

班级是否使用非托管资源是课堂内部的资源,你根本不应该关心它。如果您没有明确地处理该类,那么使用非托管资源的每个类都应该有一个终结器来清除那些非托管资源。 Dispose只是允许您以更确定和更直接的方式清理其资源(管理和非管理,尽管这并不一定意味着立即释放内存)。例如,Dispose FileStream会立即释放文件句柄,而如果您不Dispose(或Close),该文件将被打开,直到下一个收集和定稿。

修改

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

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

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

Dispose可能还会发生其他事情。例如,再次使用Windows表单,当您在Dispose上调用Control时,会发生很多事情:

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

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

答案 1 :(得分:1)

使用任何类implment IDisposable接口应该使用(...){}包装,或者在适当的地方妥善处理。