首页 > 解决方案 > 如何释放字典中对象使用的内存,还是不需要?

问题描述

我创建了一个类(下面的简化版本):

public class UsbDevice
{
    public UsbDevice()
    {
        Debug.WriteLine($"UsbDevice constructor called");
    }

    ~UsbDevice()
    {
        Debug.WriteLine($"UsbDevice destructor called");
    }
}

我使用字典来保存我所有的 UsbDevices 的列表。

Dictionary<string, UsbDevice> _devices = new Dictionary<string, UsbDevice>();

UsbDevice usbDevice = new UsbDevice();
_devices.Add("Path of the device", usbDevice);

当我不再需要 UsbDevice 时,我将其从字典中删除。

_devices.Remove("Path of the device");

(为简单起见,我省略了所有检查设备是否存在)

当我删除 UsbDevice 时,我看到没有调用析构函数。这仅在应用程序关闭时完成。所以这意味着 UsbDevice 对象仍然存在于内存中的某个地方,对吧?我知道字典的“删除”方法不会从内存中删除 UsbDevice,因为字典不知道 UsbDevice 是否可以在代码中的其他地方使用(引用)。

如何摆脱与 UsbDevice 关联的所有内存?如果我不摆脱那个内存,那么添加/删除周期会因为所有未使用的 UsbDevices 而增加内存使用量,对吧?我怎样才能避免这种情况?

标签: c#dictionarymemory

解决方案


  1. 最好让 CLR 决定何时释放内存
  2. 如果你现在真的需要释放你的内存——你可以使用 GC.Collect(); 这种方式会消耗资源,所以不建议手动使用。
  3. ~UsbDevice() 不是析构函数。这是终结者。当垃圾收集器发现这个对象可以被移除时——它会检查它是否有一个终结器。如果不是 - 它只是删除对象。如果是 - 那么对象将被放入特殊队列中,其中所有对象都具有终结器。在某个时间点将调用终结器,但对象仍位于内存中。当 GC 进行另一次迭代时——它会看到有一个已经执行的终结器——对象可以从内存中删除。这就是为什么使用终结器不是一个好习惯的原因。
  4. 如果您想释放一些非托管资源并且您确切知道何时应该发生这种情况 - 请查看 IDisposable。

推荐阅读