GC垃圾回收之GC.KeepAlive方法

根据官方的说法,GC的垃圾回收是酱子地:

垃圾回收器搜索托管代码中引用的托管对象。

垃圾回收器尝试完成没有被引用的对象。

垃圾回收器释放没有被引用的对象并回收它们的内存。

也就是说在.NET中GC是不定时的进行以上的三项工作,对在托管对象中没有任何引用的对象进行回收,当然何时运行垃圾回收是.NET说了算,也可以使用代码强制其运行回收例程,但据官方讲似乎不赞成这种做法(貌似ms除了他建议的办法,其它办法都不赞成的),说是会影响性能.

好吧就按官方说的办,但是问题出来了,请看下面代码:

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
1 public class Paramet_A
2 {
3 private byte[] p_V;
4
5 public byte[] VV
6 {
7 get { return p_V;}
8 set {p_V = value;}
9 }
10 }
11 public class NativeInvoke
12 {
13
14 [DllImport( " winmm.dll " , CharSet = CharSet.Auto, ExactSpelling = true )]
15 public static extern NativeMedhod(byte* x);
16
17 public void InvokeNativeMethod()
18 {
19 Paramet_A a = new Paramet_A();
byte* x=(byte*)a.VV;
20 NativeMedhod(x);
21 }
22 }

在上面代码中申明了两个类:Paramet_A和 NativeInvoke

Paramet_A类是作为一个参数指针传给NativeInvoke.NativeMethod的,而NativeInvoke.NativeMethod

是假定本机存在的一个调用方法,上面代码的方法InvokeNativeMethod看起来好象没有错误,确实如此,在单线程运行中或者是在GC没有运行垃圾回收时它能很好的工作,但是当语句运行到20行但没有返回时该死的GC运行了,那问题就出来了,GC发现变量a没有引用了就做了它了,而其实在非托管代码中它还要使用,这样在非托管代码中肯定出现无法预料的结果了(好象ms特喜欢这种说法,无法预料,嗨嗨,这里套用下),解决办法就是在20行后添加一行GC.KeepAlive(a),据说这样是为了防止GC来回收它,也就是说对a进行引用一下,避免20行代码没有返回时a变量被回收,哈哈这下明白了.

再请看一段代码:

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
1 public Class ThreadInvoke
2 {
3
4 private void ThreadStart_T()
5 {
6 Paramet_A a = new Paramet_A();
7 byte [] x = a.BB
8 // 下面就是做点啥的代码
9 // .......
10 if (x[ 0 ] == 1 ) // 这行代码会出问题?
11 {
12 }
13 }
14
15 public void Run()
16 {
17 Thread th = new Thread( new ThreadStart(ThreadStart_T));
th.Start();
18 }
19 }

 好了,你看Run方法,它开始了一个线程,该线程的执行体是ThreadStart_T方法,这个方法也看似没啥问题,但是假定运行到第十行的时侯GC又开始运行了,那就又是一个无法预料了,因为a被终结了,解决的办法就是在12行后加一句GC.KeepAlive(a).

说到这里有人要说了,那GC.KeepAlive这个方法不是有好多地方要用到吗?是的,从线程安全角度讲,任何局部变量都最好在它结束使命前用一下GC.KeepAlive,不过这好象也太........,幸运的是ms又说了:KeepAlive 方法除了延长作为参数传递的对象的生存期之外,不会执行任何操作,也会不产生任何其他副作用,哈哈所以说尽管用吧.

哦对了,补充一句,用在引用对象上,并且预料到该引用对象有成员被其它代码所使用.

转载于:https://www.cnblogs.com/ren700622/archive/2010/08/03/1791232.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值