CLI本机对象卡在gen2中而不是垃圾回收

时间:2016-10-18 14:42:58

标签: c# garbage-collection c++-cli dispose finalize

我正在研究这种高频生产系统。有一个C#/ CLI层调用C ++库。我们观察到的是,托管对象正在进入第二代收集器并且被“卡住”。最终,当RAM耗尽时,C#应用程序停止运行。这些托管对象是本地对象,应该具有非常短的生命周期。它们也仅被引用一次。 C#应用程序必须在包含本机资源的所有对象上调用.Dispose(),以确保强行删除所有内容。我们有很多对象,所以这不是理想的,从API的角度看是凌乱的。 CLI如下所示:

Field::~Field()
{
    if(m_pField != NULL)
    {
        delete m_pField;
        m_pField = NULL;
    }
    System::GC::SuppressFinalize(this);
}

Field::!Field()
{
    if(m_pField != NULL)
    {
        delete m_pField;
    }
}

有谁能想到为什么这些短暂的物体似乎永远不会被收集起来并释放记忆?

1 个答案:

答案 0 :(得分:3)

问题是未管理的对象不计入内存压力" GC用来决定何时进行垃圾收集的值。

您可以做的一件事是使用GC.AddMemoryPressure(让GC知道有一个与托管包装器关联的大型非托管对象。

Field::Field()
{
    //... Other stuff

    if(m_pField != NULL)
    {
        m_lSizeOfField = GetSizeOfField(m_pField);
        System::GC::AddMemoryPressure(m_lSizeOfField);
    }
}


Field::~Field()
{
    //If you had managed objects you would call "delete" here on them.
    //delete m_managedData;

    //In C++/CLI if you have unmanged resources just have the dispose method
    // call the finalizer. It is cleaner and easier to maintain.
    // You can't do this in C#
    this->!Field();

    //No need to add this next line, C++/CLI does it for you.
    //System::GC::SuppressFinalize(this);
}

Field::!Field()
{
    if(m_pField != NULL)
    {
        delete m_pField;
        m_pField = NULL;
        System::GC::RemoveMemoryPressure(m_lSizeOfField);
    }
}