.NET大量使用非托管资源时,应注意的垃圾回收
2011-12-24 19:10
405 查看
首先,先说一点当使用非托管资源时,占用的托管内存很小,非托管资源占用了大量内存。
如果一个类要包装可能很大的本地资源,就应该提示垃圾回收器实际需要消耗多少内存。垃圾回收器内部会监视内存压力,压力变大时,就强制执行垃圾回收。
命名空间System.Runtime.InteropServices 提供了 HandleCollection类
此类作用:因为当CLR使用非托管资源时产生的托管对象内存非常小 应为GC回收只会根据托管对象的内存达到一定限度才会执行垃圾回收。
比如:你调用有10个非托管资源,在进程中每个非托管资源占用1M非托管内存,产生1K托管内存, GC回收第0代的阀值是256K,写程序的兄弟操作完非托管资源也没及时Dispose()
此时运行程序 产生了10K的托管内存,10M的非托管内存,GC发现没有到我回收第0代回收阀值 10K托管内存还存活着,10M非托管资源也存活着(没及时Dispose())
此时的10M非托管内存只有会到满了GC第0代阀值回收的时候才会释放;
上面只是一个例子。
如果一个类大量使用非托管资源建议使用 应为非托管资源会产生CLR暂时控制不了的内存,应为在使用非托管资源的同时我们也会产生我们不需要的对象。
下面贴一个简单的例子:
再补充一点:
GC. AddMemoryPressure 方法
GC.RemoveMemoryPressure 方法
专门提供在GC对非托管资源使用时间内存管理方法
在确定何时安排垃圾回收时,运行时将考虑分配多少托管内存。如果一个小的托管对象分配了大量非托管内存,运行时将只考虑托管内存,从而低估安排垃圾回收的紧迫性。AddMemoryPressure 方法会将这一对系统内存的额外压力通知运行时。
在最简单的用法模式下,托管对象将在构造函数中分配非托管内存,而在 Dispose 或 Finalize 方法中释放内存。 在分配非托管内存之后,将调用 AddMemoryPressure 方法,而在释放了非托管内存之后,将调用 RemoveMemoryPressure 方法。
在复杂一些的情形中,非托管内存的分配在托管对象的生存期内会出现非常大的变化,此时您可以调用 AddMemoryPressure 和 RemoveMemoryPressure 方法将这些增量更改传递到运行时。
如果一个类要包装可能很大的本地资源,就应该提示垃圾回收器实际需要消耗多少内存。垃圾回收器内部会监视内存压力,压力变大时,就强制执行垃圾回收。
命名空间System.Runtime.InteropServices 提供了 HandleCollection类
此类作用:因为当CLR使用非托管资源时产生的托管对象内存非常小 应为GC回收只会根据托管对象的内存达到一定限度才会执行垃圾回收。
比如:你调用有10个非托管资源,在进程中每个非托管资源占用1M非托管内存,产生1K托管内存, GC回收第0代的阀值是256K,写程序的兄弟操作完非托管资源也没及时Dispose()
此时运行程序 产生了10K的托管内存,10M的非托管内存,GC发现没有到我回收第0代回收阀值 10K托管内存还存活着,10M非托管资源也存活着(没及时Dispose())
此时的10M非托管内存只有会到满了GC第0代阀值回收的时候才会释放;
上面只是一个例子。
如果一个类大量使用非托管资源建议使用 应为非托管资源会产生CLR暂时控制不了的内存,应为在使用非托管资源的同时我们也会产生我们不需要的对象。
下面贴一个简单的例子:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.IO; namespace ConsoleApplication6 { class Program { static void Main(string[] args) { Temp temp = new Temp(); temp = null; TestHandleCollector test = new TestHandleCollector(); Console.ReadLine(); } } class TestHandleCollector { public TestHandleCollector() { //制定当前类超过指定数量的非托管资源强制执行垃圾回收 注意:此时只执行第0代垃圾回收 GC只会回收第0代 HandleCollector temp = new HandleCollector("testHandle", 2); Console.WriteLine("当前强制回收第0代的非托管资源阀值为:" + temp.InitialThreshold.ToString()); temp.Add(); temp.Add(); temp.Add(); Console.WriteLine("当前非托管资源句柄数量:" + temp.Count.ToString()); File.Create(@"c:\text.txt"); File.Create(@"c:\text1.txt"); File.Create(@"c:\text11.txt"); temp.Remove(); temp.Remove(); temp.Remove(); Temp temp1 = new Temp(); temp1 = null; temp.Add(); temp.Add(); temp.Add(); Console.WriteLine("当前非托管资源句柄数量:" + temp.Count.ToString()); File.Create(@"c:\text11.txt").Dispose(); //前面创建File我并没有Dispose GC会自动释放非托管资源 不然此处会报错 } } class Temp { ~Temp() { Console.WriteLine("执行了第0代垃圾回收!"); } } }
再补充一点:
GC. AddMemoryPressure 方法
GC.RemoveMemoryPressure 方法
专门提供在GC对非托管资源使用时间内存管理方法
在确定何时安排垃圾回收时,运行时将考虑分配多少托管内存。如果一个小的托管对象分配了大量非托管内存,运行时将只考虑托管内存,从而低估安排垃圾回收的紧迫性。AddMemoryPressure 方法会将这一对系统内存的额外压力通知运行时。
在最简单的用法模式下,托管对象将在构造函数中分配非托管内存,而在 Dispose 或 Finalize 方法中释放内存。 在分配非托管内存之后,将调用 AddMemoryPressure 方法,而在释放了非托管内存之后,将调用 RemoveMemoryPressure 方法。
在复杂一些的情形中,非托管内存的分配在托管对象的生存期内会出现非常大的变化,此时您可以调用 AddMemoryPressure 和 RemoveMemoryPressure 方法将这些增量更改传递到运行时。
相关文章推荐
- 是否可以完全相信垃圾回收?.Net 托管资源 非托管资源 垃圾回收 的疑问。
- .NET的堆和栈04,对托管和非托管资源的垃圾回收以及内存分配
- 是否可以完全相信垃圾回收?.Net 托管资源 非托管资源 垃圾回收 的疑问。
- .net最佳实践二:使用finalize/dispose模式提升垃圾回收器性能
- .NET对象的创建、垃圾回收、非托管资源的手动处理
- .NET垃圾回收 – 非托管资源
- 浅谈.NET非托管资源垃圾回收与程序资源优化(弱引用)
- .NET对象的创建、垃圾回收、非托管资源的手动处理
- 使用 .net 2.0 中 linkLabel 控件要注意的一点
- Go 的垃圾回收机制在实践中有哪些需要注意的地方?
- .NET使用Office Open XML导出大量数据到 Excel
- [转载CSDN]在.NET里的垃圾回收编程 Paul_Ni(原作)
- .net下导致Session失效的一种情况:js教本中使用window.open和window.showModalDialog时需要注意
- .NET垃圾回收机制 转
- 在使用.NET 加解密需要注意的问题
- .NET垃圾回收的机制解释
- .NET垃圾回收:非托管资源,IDispose和析构函数的结合
- .net的垃圾回收机制[转]
- c#学习笔记-.net垃圾回收机制
- .NET垃圾回收 问题、建议