【发布时间】:2020-08-29 08:50:09
【问题描述】:
如果没有内存泄漏,我无法销毁 InkEdit。 Dispose 方法有一点帮助,但仍然没有释放大量非托管资源。
// Create 16 InkEdit components
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
var ie = new InkEdit { Left = x * 50, Top = y * 50, Width = 40, Height = 40 };
panel1.Controls.Add(ie);
}
}
修改示例以正确处理所有控件。
// 46 MiB of leaked RAM after every Create/Dispose iteration
while (panel1.Controls.Count > 0)
{
var lastIndex = panel1.Controls.Count - 1;
var control = panel1.Controls[lastIndex];
panel1.Controls.RemoveAt(lastIndex);
control.Dispose();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
使用 GC.Collect:
没有 GC.Collect:
【问题讨论】:
-
panel1.Controls.Clear();当然不会处理任何东西。你调用control.Dispose();的foreach循环是错误的,你不能修改你正在迭代的集合,你不会处理所有控件。 清除 Controls 集合仍然是Controls.Clear()。使用向后的for循环(从panel1.Controls.Count - 1到0)。你可以在循环之后只调用GC.Collect(),它不会有太大的不同。 -
我猜这不是泄漏。由于对未来对象实例分配的优化,GC 只是保持内存在使用中。处理和收集并不意味着releasing内存。
-
@aepot 该代码确实在泄漏:OP 没有处理那些控件(确实需要处理),因此内存使用量会不断增加。无论如何,代码只需要一点点修复(已经描述过)。
-
@Jimi 不,GC 将自动为所有
IDisposable对象调用终结器。我希望该类即使内部有非托管资源也能正确实现。结果,不会有泄漏。无论如何,问题信息中提供的内存屏幕截图与泄漏无关。我知道某些 .NET 类在极少数情况下可能会泄漏,但这种情况很常见,不会导致真正的泄漏。我建议 OP 进一步了解 CLR 中的垃圾收集。 -
@aepot 技术上,这正是它所做的,也是它应该做的。
标签: c# winforms memory-leaks