MTR*_*MTR 2 c# garbage-collection memory-leaks
在搜索内存泄漏时,我发现了一件奇怪的事情,我不知道它是否正常.
为了找到内存泄漏,我创建了一个带有新按钮和按钮检查的小测试应用程序:
List<WeakReference> WeakReferences = new List<WeakReference>();
private void Button_New(object sender, RoutedEventArgs e)
{
WeakReferences.Add(new WeakReference(new ObjectUnderTest()));
// Adding a bunch of other objects to test here
}
private void Button_Check(object sender, RoutedEventArgs e)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
int AliveCounter = 0;
foreach (var item in WeakReferences)
{
if (item.IsAlive)
{
AliveCounter++;
Debug.WriteLine("Object " + item.Target.GetType().ToString() + " still alive!");
}
}
if (AliveCounter > 0)
{
MessageBox.Show(AliveCounter.ToString() + " objects still alive!");
}
else
{
MessageBox.Show("No objects alive!");
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我的大多数测试对象都能正确收集垃圾,但仍有一些对象仍处于活动状态.
经过更多测试后,我发现这些对象确实被垃圾收集,但只有在我点击检查按钮之前切换到另一个应用程序.
您认为,这是一种正常行为,还是内存泄漏,我必须解决?
附加信息:目前我认为这确实是一个问题,但也许它不会出现在我们的生产代码中.
如果GC.Collect()在没有GCCollectionMode参数的情况下调用,那么GCCollectionMode.Default在大多数版本的CLR中使用的是GCCollectionMode.Forced强制集合发生的相同.要确保您强制收集,请尝试呼叫GC.Collect(GCCollectionMode.Forced).
如果你仍然发现对象保持活着,这可能是由于你的线程与并发集合竞争(并发集合在大多数环境中是默认的)或者你的ObjectUnderTest类型是自我复活或者有一个复杂的引用路径令人困惑GC的第一次通过(不太可能的情况,但你永远不知道)?
一般来说,GC将决定何时是收集给定对象的最佳时间,并且此行为是不确定的(除非您正在呼叫GC.Collect(GCCollectionMode.Forced)或等效).在某些边缘情况下,有必要影响垃圾收集器的行为,但在大多数情况下,最好让GC做它的事情而不用担心它的效率如何.这通常足够有效,并且为了使其更有效地运行可能是非常困难和涉及的.