.NET大量使用非托管资源时,应注意的垃圾回收


首先,先说一点当使用非托管资源时,占用的托管内存很小,非托管资源占用了大量内存。

如果一个类要包装可能很大的本地资源,就应该提示垃圾回收器实际需要消耗多少内存。垃圾回收器内部会监视内存压力,压力变大时,就强制执行垃圾回收。

命名空间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 方法会将这一对系统内存的额外压力通知运行时。

在最简单的用法模式下,托管对象将在构造函数中分配非托管内存,而在 DisposeFinalize 方法中释放内存。 在分配非托管内存之后,将调用 AddMemoryPressure 方法,而在释放了非托管内存之后,将调用 RemoveMemoryPressure 方法。

在复杂一些的情形中,非托管内存的分配在托管对象的生存期内会出现非常大的变化,此时您可以调用 AddMemoryPressure 和 RemoveMemoryPressure 方法将这些增量更改传递到运行时。

转载于:https://www.cnblogs.com/skolley/archive/2011/12/24/2300600.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值