有关.net中内存管理的疑问

我正在学习C#中的“Professional C#”中的内存管理

垃圾收集器的存在意味着你通常不会担心你不再需要的对象; 您只需简单地允许对这些对象的所有引用超出范围,并允许垃圾回收器根据需要释放内存。 但是,垃圾收集器不知道如何释放非托管资源(如文件句柄,网络连接和数据库连接)。 当托管类封装对非托管资源的直接或间接引用时,需要做出特别的规定,以确保在垃圾收集类的实例时释放非托管资源。

定义类时,可以使用两种机制来自动释放非托管资源。

  • 声明一个析构函数(或finalizer)作为你的类的成员。
  • 在你的类中实现System.IDisposable接口。
  • 我不明白几件事情:

  • “非托管资源(如文件句柄,网络连接和数据库连接)”。 对他们有什么大不了的? 他们怎么没有管理? (或)GC为什么不能管理这些资源?

  • 我们将在一个类的finalizer或Dispose()方法中放置什么代码以及该代码看起来像什么? 一些使用这些资源的例子会有很多帮助。


  • 这里真正的问题是紧迫性。 由于垃圾收集器明确地跟踪内存,它会知道何时需要通过清除未引用的对象来释放内存。 这可能会每分钟发生几次,或者每小时发生一次,甚至从不发生(如果不需要创建新的对象)。 但重要的是,它在需要时确实发生。

    但记忆不是唯一有限的资源。 拿档案。 通常,一次只有一个应用程序可以打开一个文件,因为如果多个人试图写入同一个文件,可能会变得混乱。 数据库的连接数量有限。 等等。 垃圾收集器不跟踪任何这些资源。 它不知道关闭它们有多紧急。

    当然,你可以打开一个FileStream,然后在没有关闭的情况下读取它。 如果您清除对该对象的引用,最终垃圾收集器可能会决定收集FileStream对象,该对象将运行Finalizer并将文件正确关闭。 但是这可能需要很长时间,同时文件被锁定。

    使用数据库连接时,它更加紧迫,因为可用集合数量非常有限,所以如果打开过多的连接而不处理它们,最终会出错,因为您将有一堆数据库对象具有打开的连接在垃圾收集器队列中等待。

    妥善处理一次性物品是一种好的做法。 有时候你可能不会这样做,但它是不好的风格。 如果一个对象实现了IDisposable,那是因为它希望在完成使用后清理它。


    .NET框架上的一些类只是Windows API或第三方程序集的包装。 这些API不是托管代码(它们可以用C ++编写,也可以是旧的COM程序集),垃圾收集器不知道应用程序何时不再需要它们。

    例如,当您打开一个磁盘文件时,它将保持打开状态,直到您告诉它关闭该文件。 如果在不关闭文件的情况下销毁指向该文件的指针(即离开作用域),该文件将保持打开状态并锁定。

    在框架上为这些类实现的Dispose方法调用了以干净的方式最终确定实例所需的内部Close方法。 因此,所有包装非托管代码的类都应该实现Disposable接口,以确保它实现的关闭方法。

    然后当你实例化这个类时,最好使用using语句来完成它,因为当你离开作用域时,Dispose方法会自动调用。


    1.)GC不知道如何正确关闭外部资源。 当然,他可以杀死一个网络连接(实际上,如果你不断开连接,即数据库连接,他会这么做)。 但是数据库没有被通知关闭连接。

    类似的文件流。 缓冲区中还有东西吗? 这是否必须在关闭文件句柄之前写入文件? GC不知道这个 - 访问代码。

    2.)接下来是什么。 因此,如果您有打开的文件流和内部缓冲区 - 在dispose方法中,您可以刷新缓冲区,将其写入文件并关闭文件hanlde。

    通常情况下,您不直接访问数据库。 你使用库来管理这个。

    在大多数情况下,如果您的类正在处理中,就可以部署这些外部资源管理器(Db连接,文件流,网络类)。

    链接地址: http://www.djcxy.com/p/9229.html

    上一篇: doubts regarding Memory management in .net

    下一篇: How to manage IDisposable Objects that are cached?