C# CLI本机对象卡在gen2中而未被垃圾收集
我正在研究这个高频生产系统。有一个C/CLI层,它调用C++库。我们观察到的是,托管对象正在进入garabage收集器的第2代,并“卡住”。随着RAM耗尽,C#应用程序最终会停止运行。这些托管对象是本地对象,应该具有非常短的生存期。此外,它们仅被引用一次。C#应用程序必须对其所有包含本机资源的对象调用.Dispose(),以确保强制删除所有内容。我们有相当多的对象,所以这不是理想的,从API的角度来看是混乱的。CLI如下所示: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
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,我们所做的分析是不正确的。斯科茨的推理是有道理的。还有其他选择吗?因为发现我们的一些原生物体的大小是非常棘手的,而且不是一门精确的科学。有其他选择吗?因为发现我们的一些原生物体的大小是非常棘手的,不是一门精确的科学。