C# CLI本机对象卡在gen2中而未被垃圾收集

C# CLI本机对象卡在gen2中而未被垃圾收集,c#,garbage-collection,c++-cli,dispose,finalize,C#,Garbage Collection,C++ Cli,Dispose,Finalize,我正在研究这个高频生产系统。有一个C/CLI层,它调用C++库。我们观察到的是,托管对象正在进入garabage收集器的第2代,并“卡住”。随着RAM耗尽,C#应用程序最终会停止运行。这些托管对象是本地对象,应该具有非常短的生存期。此外,它们仅被引用一次。C#应用程序必须对其所有包含本机资源的对象调用.Dispose(),以确保强制删除所有内容。我们有相当多的对象,所以这不是理想的,从API的角度来看是混乱的。CLI如下所示: Field::~Field() { if(m_pField

我正在研究这个高频生产系统。有一个C/CLI层,它调用C++库。我们观察到的是,托管对象正在进入garabage收集器的第2代,并“卡住”。随着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;
    }
}

有人能想一想为什么这些短期对象似乎从未被收集并释放内存吗?

问题是非托管对象不计入GC用来决定何时进行垃圾收集的“内存压力”值

您可以做的一件事是让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);
    }
}

问题是非托管对象不计入GC用来决定何时进行垃圾收集的“内存压力”值

您可以做的一件事是让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);
    }
}

它被称为非
C#/CLI
。确保使用正确的术语,否则在搜索问题的解决方案时很难找到相关信息。临时对象可以升级到gen#2的实际情况并不多。Crystal ball表示终结器线程已死锁。用非托管调试器查看一下。回顾一下,这些东西进入gen 1,我们所做的分析是不正确的。斯科茨推理是有道理的。它被称为非
C#/CLI
。确保使用正确的术语,否则在搜索问题的解决方案时很难找到相关信息。临时对象可以升级到gen#2的实际情况并不多。Crystal ball表示终结器线程已死锁。用非托管调试器查看一下。回顾一下,这些东西进入gen 1,我们所做的分析是不正确的。斯科茨的推理是有道理的。还有其他选择吗?因为发现我们的一些原生物体的大小是非常棘手的,而且不是一门精确的科学。有其他选择吗?因为发现我们的一些原生物体的大小是非常棘手的,不是一门精确的科学。