1

假设我有一个大Image对象,如果我调用Dispose()这个对象的方法,我可以很容易地看到我的应用程序的内存消耗减少了,因为我刚刚从内存中清除了对象。

但是,如果我有自己的类型/类并想要处理它的一个实例,比方说,它包含一个数组(我认为这与类内部具有byte[]的相同),该怎么办。Image我将如何着手实现IDisposable,所以当Dispose()被调用时byte[]会立即从内存中释放出来。不用我等GC

如果它是 astring而不是 abyte[]怎么办?

4

2 回答 2

2

只要存在对它们的某种引用,.NET 中的对象就存在。不存在的对象不包含对任何内容的引用。如果在垃圾回收周期中发现一个对象在除WeakReference目标之外的任何地方都没有对其的引用,则系统将使这些WeakReference对象无效,因此这些对象将不再有任何指向它们的引用,因此将不复存在。如果对某个对象的唯一非弱引用在系统的已注册Finalize方法的对象列表中,则该对象将从该列表中删除并添加到系统的对象列表中,该对象的Finalize方法应在第一时间运行。一旦系统运行的是一个对象的Finalize方法,它将从后一个列表中删除,除非引用已存储在其他地方,否则它将不复存在。

有一个 dispose 方法的原因Image是它的构造经常要求创建不是 .NET 对象的东西和/或要求外部实体代表它做一些事情(例如授予对文件的独占读取访问权限)。如果 aBitmap在没有被调用的情况下被放弃Dispose,并且如果它没有Finalize方法,则该Bitmap对象将不复存在,但它请求创建的任何外部对象将继续存在,任何代表它执行操作的外部实体将继续存在将继续这样做。

因为字节数组的创建不需要构造任何不是 .NET 对象的东西,也不需要任何外部实体代表它做任何事情,所以不需要一个不再需要的数组做任何事,除了不复存在。对于拥有这样一个数组的对象也是如此。

于 2013-05-15T19:23:29.163 回答
2

内存消耗在两种情况下减少:

  1. 垃圾收集器已释放内存,并且
  2. 执行了非托管代码,它立即释放了内存。

图像数据示例是第二种情况。图像由操作系统保存,当您处理图像时,会调用操作系统来释放图像缓冲区。这是操作系统的工作,因为操作系统是在屏幕上渲染图像的系统,这取决于硬件和驱动程序。除此之外,图形操作系统在处理图像数据方面进行了极大的优化——难怪它在需要时用于处理图像。

当您创建自己的一次性类时,情况完全相反。关于内存占用,执行 dispose 实际上什么也没做。只要有一个指向已处理类的活动指针,即使垃圾收集也不会减少内存使用量。

只有在分配一些非托管资源时,类才应该实现 IDisposable - 文件句柄、图像、套接字(从操作系统的角度来看,它们只是一种文件句柄)等。 Dispose 方法应该只释放非托管资源。将字段设置为 null 并做类似的愚蠢事情是没有意义的。

于 2013-05-15T20:14:08.140 回答