我在.NET CF应用程序中遇到内存泄漏问题。
使用RPM我发现动态创建控件不会按预期进行垃圾回收。在.NET Window Forms中运行相同的代码行为有所不同,并按照我的预期处理控件。
通过PerfMon查看RPM输出 Process Heap 计数器:
GC堆:
我最好的猜测是,对小组的弱引用是出于某种未知的原因而没有使该对象符合GC的条件,可以吗?
请注意:即使 Dispose()解决了样本的问题,我也不能轻易将其合并到现有的应用程序中,因为它不是那么清晰确定对象何时不再使用。
我已经包含了源代码的简化版本来说明问题:
using System;
using System.Windows.Forms;
namespace CFMemTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Calling this event handler multiple times causes the memory leak
private void Button1_Click(object sender, EventArgs e)
{
Panel uc = new Panel();
// Calling uc.Dispose() cleans up the object
}
}
}
更新:
1.调用GC.Collect()也不会导致面板被清理。
2.在Windows CE 4.2设备上使用.NET CF 2.0 SP1。
答案 0 :(得分:3)
此处的一些其他信息可以解释此行为。
NETCF上的所有UI都是 故意从GC范围中删除 永远不会收集。这种行为 与桌面有所不同 在NETCF V3.5中更改(除非运行 在兼容模式下。)
因为管理的UI,它是如此不同 NETCF上的类完全是 与桌面不同。他们很瘦 本机实现的包装器 这是实现可接受的 性能
我不确定是否有这样的资源。 但实际上,您需要知道的是: 它永远不会收集,必须打电话 处置。你真的应该这样做 在桌面上,但如果你不这样做 它的方式更宽容。不久 NETCF。
答案 1 :(得分:2)
表单不会自动处理在其代码中创建的所有控件,因为它无法知道它存在。要使表单在表单处理时自动处理它,您需要将其添加到Controls集合中。
现在你的情况可能没有做任何事情。我不知道你的例子是人为的,还是现实世界。如果它是真实的,那么行为是预期的,因为当变量超出范围时不会收集Panel(不确定它是否也在桌面上)。它可用于收集,但这仅仅意味着在下一个收集过程中它将被扫描。除非你造成GC,否则它不会被释放。
我强烈建议您查看MSDN webcast on memory management in the CF。它提供了一个更彻底的解释,说明了幕后发生的事情 - 远远超过我们在这里给出的答案。
答案 2 :(得分:1)
你确定你有内存泄漏吗? .NET Compact Framework垃圾收集器的工作方式与完整.NET框架中的垃圾收集器略有不同。来自Steven Pratschner's blog:
在以下任一情况下启动集合:
已分配1MB的对象,
将应用程序移至后台
发生内存分配失败
应用程序调用GC.Collect。
答案 3 :(得分:1)
我认为您还需要动态删除Button Click EventHandler,正如您在此博客中看到的那样: http://blogs.msdn.com/stevenpr/archive/2007/03/08/finding-managed-memory-leaks-using-the-net-cf-remote-performance-monitor.aspx
它也来自Steven Pratschner。
顺便说一句,上面提到的网络直播在这里链接: http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?culture=en-US&EventID=1032318791&CountryCode=US
希望这有帮助!