I have a problem with a memory leak in a .NET CF application.
我在.NET CF应用程序中存在内存泄漏问题。
Using RPM I identified that dynamically creating controls are not garbage collected as expected. Running the same piece of code in .NET Window Forms behave differently and disposes the control as I expected.
使用RPM我发现动态创建控件不是按预期方式进行垃圾回收。在.NET Window Forms中运行相同的代码行为有所不同,并按我的预期处理控件。
See the output from RPM via PerfMon for the Process Heap counter:
通过PerfMon查看RPM输出的Process Heap计数器:
GC Heap:
My best guess is that the Weak Reference to the Panel is for some unknown reason not making the object eligible for GC, can it be?
我最好的猜测是,对小组的弱参考是出于某种未知的原因而没有使该对象符合GC的条件,是不是?
Please note: Even though Dispose() solves the problem for the sample, I can't easily incorporate it into the existing application as it is not as clear cut to determine when the object is no longer in use.
请注意:尽管Dispose()解决了样本的问题,但我不能轻易地将其合并到现有的应用程序中,因为它不能确定何时不再使用该对象。
I have included a simplified version of the source to illustrate the problem:
我已经包含了源代码的简化版本来说明问题:
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
}
}
}
Update:
1. Calling GC.Collect() also doesn't result in the panels being cleaned up.
2. Using .NET CF 2.0 SP1 on a Windows CE 4.2 device.
更新:1。调用GC.Collect()也不会导致面板被清理。 2.在Windows CE 4.2设备上使用.NET CF 2.0 SP1。
4 个解决方案
#1
3
Some additional information here that explains this behaviour.
此处的一些其他信息可解释此行为。
据伊利亚图马诺夫说:
Everything UI related on NETCF is intentionally removed from GC scope so it is never collected. This behavior is different from desktop and has been changed in NETCF V3.5 (unless running in compatibility mode).
NETCF上的所有UI相关都是有意从GC范围中删除的,因此永远不会收集它。此行为与桌面不同,并已在NETCF V3.5中更改(除非在兼容模式下运行)。
It is so different because managed UI classes on NETCF are completely different from desktop. They are thin wrappers over native implementation which was needed to achieve acceptable performance.
它是如此不同,因为NETCF上的托管UI类与桌面完全不同。它们是本机实现的薄包装器,是实现可接受性能所必需的。
I’m not sure there’s such a resource. But really, all you need to know is: it’s never collected, must call dispose. You actually should do that on desktop as well but if you don’t its way more forgiving. Not so on NETCF.
我不确定是否有这样的资源。但实际上,你需要知道的是:它从未收集过,必须要求处理。你实际上也应该在桌面上做到这一点,但如果你不这样做更宽容。在NETCF上不是这样。
#2
2
A Form does not automatically Dispose all Controls created in its code, as it has no way to know it exists. To get the Form to Form to Dispose it automatically when it's Disposed, you need to add it to the Controls collection.
表单不会自动处理在其代码中创建的所有控件,因为它无法知道它存在。要使表单在表单处理时自动处理它,您需要将其添加到Controls集合中。
Now in your case that may not do anything. I can't tell if your example is contrived, or real world. If it's real-world, then the behavior is expected, as the Panel doesn't get collected when the variable goes out of scope (not sure it does on the desktop either). It becomes available for collection, but that simply means that on the next collection pass it will be swept. Unless you're causing a GC, then it's not going to be freed.
现在你的情况可能没有做任何事情。我不知道你的例子是人为的,还是现实世界。如果它是真实的,那么行为是预期的,因为当变量超出范围时不会收集Panel(不确定它是否也在桌面上)。它可用于收集,但这只是意味着在下一个收集过程中它将被扫描。除非你造成GC,否则它不会被释放。
I'd highly recommend you take a look at the MSDN webcast on memory management in the CF. It provides a much more thorough explanation as to what's happening under the hood - far more than we could provide in an answer here.
我强烈建议您查看CF中关于内存管理的MSDN网络广播。它提供了一个更全面的解释,说明幕后发生了什么 - 远远超过我们在这里给出的答案。
#3
1
Are you sure you have a memory leak? The .NET Compact Framework garbage collector works slightly differently to the one in the full .NET framework. From Steven Pratschner's blog:
你确定你有内存泄漏吗? .NET Compact Framework垃圾收集器的工作方式与完整.NET框架中的垃圾收集器略有不同。来自Steven Pratschner的博客:
A collection is initiated when either:
在以下任一情况下启动集合:
1MB of objects have been allocated,
已分配1MB对象,
An application is moved to the background,
应用程序移到后台,
A failure to allocate memory occurs
发生分配内存失败
An application calls GC.Collect.
应用程序调用GC.Collect。
#4
1
I think you need to dynamically remove the Button Click EventHandler too, as you can see from this blog : http://blogs.msdn.com/stevenpr/archive/2007/03/08/finding-managed-memory-leaks-using-the-net-cf-remote-performance-monitor.aspx
我认为您还需要动态删除Button Click EventHandler,正如您可以从此博客中看到的那样:http://blogs.msdn.com/stevenpr/archive/2007/03/08/finding-managed-memory-leaks-using -the净CF-远程性能monitor.aspx
It is from Steven Pratschner too.
它也来自Steven Pratschner。
By the way, the webcast mentioned above is linked here: http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?culture=en-US&EventID=1032318791&CountryCode=US
顺便说一下,上面提到的网络广播链接在这里:http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?culture = en-US&EventID = 1032318791&CountryCode = US
Hope this helps!
希望这可以帮助!
#1
3
Some additional information here that explains this behaviour.
此处的一些其他信息可解释此行为。
据伊利亚图马诺夫说:
Everything UI related on NETCF is intentionally removed from GC scope so it is never collected. This behavior is different from desktop and has been changed in NETCF V3.5 (unless running in compatibility mode).
NETCF上的所有UI相关都是有意从GC范围中删除的,因此永远不会收集它。此行为与桌面不同,并已在NETCF V3.5中更改(除非在兼容模式下运行)。
It is so different because managed UI classes on NETCF are completely different from desktop. They are thin wrappers over native implementation which was needed to achieve acceptable performance.
它是如此不同,因为NETCF上的托管UI类与桌面完全不同。它们是本机实现的薄包装器,是实现可接受性能所必需的。
I’m not sure there’s such a resource. But really, all you need to know is: it’s never collected, must call dispose. You actually should do that on desktop as well but if you don’t its way more forgiving. Not so on NETCF.
我不确定是否有这样的资源。但实际上,你需要知道的是:它从未收集过,必须要求处理。你实际上也应该在桌面上做到这一点,但如果你不这样做更宽容。在NETCF上不是这样。
#2
2
A Form does not automatically Dispose all Controls created in its code, as it has no way to know it exists. To get the Form to Form to Dispose it automatically when it's Disposed, you need to add it to the Controls collection.
表单不会自动处理在其代码中创建的所有控件,因为它无法知道它存在。要使表单在表单处理时自动处理它,您需要将其添加到Controls集合中。
Now in your case that may not do anything. I can't tell if your example is contrived, or real world. If it's real-world, then the behavior is expected, as the Panel doesn't get collected when the variable goes out of scope (not sure it does on the desktop either). It becomes available for collection, but that simply means that on the next collection pass it will be swept. Unless you're causing a GC, then it's not going to be freed.
现在你的情况可能没有做任何事情。我不知道你的例子是人为的,还是现实世界。如果它是真实的,那么行为是预期的,因为当变量超出范围时不会收集Panel(不确定它是否也在桌面上)。它可用于收集,但这只是意味着在下一个收集过程中它将被扫描。除非你造成GC,否则它不会被释放。
I'd highly recommend you take a look at the MSDN webcast on memory management in the CF. It provides a much more thorough explanation as to what's happening under the hood - far more than we could provide in an answer here.
我强烈建议您查看CF中关于内存管理的MSDN网络广播。它提供了一个更全面的解释,说明幕后发生了什么 - 远远超过我们在这里给出的答案。
#3
1
Are you sure you have a memory leak? The .NET Compact Framework garbage collector works slightly differently to the one in the full .NET framework. From Steven Pratschner's blog:
你确定你有内存泄漏吗? .NET Compact Framework垃圾收集器的工作方式与完整.NET框架中的垃圾收集器略有不同。来自Steven Pratschner的博客:
A collection is initiated when either:
在以下任一情况下启动集合:
1MB of objects have been allocated,
已分配1MB对象,
An application is moved to the background,
应用程序移到后台,
A failure to allocate memory occurs
发生分配内存失败
An application calls GC.Collect.
应用程序调用GC.Collect。
#4
1
I think you need to dynamically remove the Button Click EventHandler too, as you can see from this blog : http://blogs.msdn.com/stevenpr/archive/2007/03/08/finding-managed-memory-leaks-using-the-net-cf-remote-performance-monitor.aspx
我认为您还需要动态删除Button Click EventHandler,正如您可以从此博客中看到的那样:http://blogs.msdn.com/stevenpr/archive/2007/03/08/finding-managed-memory-leaks-using -the净CF-远程性能monitor.aspx
It is from Steven Pratschner too.
它也来自Steven Pratschner。
By the way, the webcast mentioned above is linked here: http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?culture=en-US&EventID=1032318791&CountryCode=US
顺便说一下,上面提到的网络广播链接在这里:http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?culture = en-US&EventID = 1032318791&CountryCode = US
Hope this helps!
希望这可以帮助!