.Net托管资源非托管资源垃圾回收的疑问

CLR为开发者提供了一个非常让人激动的功能--垃圾回收。但是园子里关于垃圾回收的讨论,大多是讨论垃圾回收的原理,以及Dispose模式。但是垃圾回收在实际使用时,是不是可以达到其设计的目标,在开发过程中有没有需要注意的问题呢?本人也不是非常明确,这篇文章希望能达到抛砖引玉的效果,希望个人牛人能够给本人或同样存在疑惑的人一个清楚明确的答案。

什么是垃圾回收?就是说你在使用CLR的时候(不包含托管资源) ,只需要new一个对象使用。而不需要通过程序代码进行释放对象(以上是本人理解的垃圾回收的意义)。

托管资源 非托管资源

托管资源和非托管资源的区别通常会让开发者弄不清楚,到底什么是托管的,什么不是托管的。这里说一下自己的体会。如果你使用的Class是属于CLR的,不管它实际上使用的什么资源。CLR都会帮你进行垃圾回收。简单的比如一个List对象,你使用完成(变量脱离其作用域)就会被CLR自动回收。那么对于网上常说的数据连接,文件类呢?其实同样会在使用完成后被自动回收,但是因为此类资源很重要,而垃圾回收的时机不确定。所以很多教材上说此类资源需要在使用完成后及时释放(通过程序代码)。这里说明一点就是CLR的Class都会被自动回收,无论它实际控制的是托管资源还是非托管资源。

这里可以做一个简单的测试,一个WinForm项目,两个Button(button1, button2) ,点击事件如下。

private void button1_Click(object sender, EventArgs e)

{

FileStream file = new FileStream(@"c:\DisposeTest.txt", FileMode.Open);

}

private void button2_Click(object sender, EventArgs e)

{

GC.Collect();

}

连续点击button1,第二次就会报错,说明文件没有被释放。但是如果点击button1再点击button2再点击button1那么就不会报错了,因为button2垃圾回收将文件释放了。

那么哪些资源,对象是不能自动回收,必须通过程序代码释放的呢?简单的说你使用的Class, 组件不属于CLR。比如Win32API,Com组件等。使用上述类型的时候,如果分配了资源,那么一定要通过代码进行释放。还是文件打开的例子,如果是使用 Win32API打开文件,那么使用垃圾回收是没有办法释放资源的。所以一定要在代码中进行相关资源的释放。

垃圾回收在开发中的问题 

托管资源,非托管资源已经说清楚了。垃圾回收的原理这里就不说了,网上很多文章介绍。下面我们说一下在实际开发过程中是不是可以完全相信垃圾回收,而不需要考虑对象的释放呢?或者哪些对象是需要及时释放的呢?本人主要是是从事WinForm开发。所以下面的讨论可能是以WinForm为背景。 一下是目前本人明确或者未明确的内容希望与大家讨论。

1)哪些资源需要及时释放?这个问题很明确了,数据库连接,文件,还有其他的大家补充吧。就想到这么多。

2)WinForm背景下,如果创建的Form被释放(Form = null)的时候,Form内的字段(比如,String, DataTable, 其他自定义类)是否会被自动释放(假设这些字段没有被其他的地方引用)。

3)因为从事的是数据库相关开发,自然用到最多的是ADO.Net,那么除了Connection,其他的对象是否需要及时释放,哪些对象是否需要及时释放(这里比较关心的是DataSet, DataTable)?

4)补充一点如果上述很多对象都需要及时释放,那么垃圾回收的意义是不是就一定程度的降低了呢?

以上是个人对垃圾回收的理解和疑问,希望大家能够一起讨论,最后能有明确的结论。

时间: 2024-10-31 07:36:17

.Net托管资源非托管资源垃圾回收的疑问的相关文章

.net非托管资源的回收方法_实用技巧

本文实例讲述了.net非托管资源的回收方法,分享给大家供大家参考.具体分析如下: 释放未托管的资源有两种方法   1.析构函数 2.实现System.IDisposable接口   一.析构函数  构造函数可以指定必须在创建类的实例时进行的某些操作,在垃圾收集器删除对象时,也可以调用析构函数.析构函数初看起来似乎是放置释放未托管资源.执行一般清理操作的代码的最佳地方.但是,事情并不是如此简单.由于垃圾回收器的运行规则决定了,不能在析构函数中放置需要在某一时刻运行的代码,如果对象占用了宝贵而重要的

如何区别 托管资源 与 非托管资源 ??

问题描述 C#.NET里如何区别托管与非托管资源,以防止忘记释放某个非托管资源而导致内存爆满?我很困惑,尤其是数据库链接OleDbConnection或是SqlConnection这些Conn对象,是直接用.Dispose()就可以放心了呢还是必须.Close()和.Dispose()一起用才放心不会导致内存爆炸? 解决方案 解决方案二:实现IDisposable的类可以使用Dispose()方法释放其中的非托管资源也就是说如果你的类中用到如文件流网络链接等具有受保护的Finalize方法的类型

.NET简谈互操作(四:基础知识之Dispose非托管内存)

互操作系列文章: .NET简谈互操作(一:开篇介绍) .NET简谈互操作(二:先睹为快) .NET简谈互操作(三:基础知识之DllImport特性) .NET简谈互操作(四:基础知识之Dispose非托管内存) .NET简谈互操作(五:基础知识之Dynamic平台调用)  .NET简谈互操作(六:基础知识之提升平台调用性能) .NET简谈互操作(七:数据封送之介绍) 我们继续.NET互操作学习.前一篇文章中我们学习了基础知识中的DllImport关键特性:我们继续学习基础知识中的内存释放相关技术

C# 托管内存与非托管内存之间的转换(结合Unity3d的实际开发)

1.c#的托管代码和非托管代码 c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存,然而c#毕竟运行在c++之上,有的时候,(比如可能我们需要引入一些第三方的c++或native代码的库,在Unity3d开发中很常见)我们需要直接在c#中操纵非托管的代码,这些non-managed memory我们就需要自己去处理他们的申请和释放了, c# 中提供

c#- 托管DLL无法加载非托管Dll,怎么办?

问题描述 托管DLL无法加载非托管Dll,怎么办? 比如报错,"无法加载 DLL"libcurl.dll": 找不到指定的模块" 我已经引用了托管DLL libcurlNET.dll,这个托管DLL需要引用libcurl.dll,两个DLL已经放在了同一个目录下,还是报错,请指点·· 解决方案 C#用不着这个库,你直接用httpwebrequest就可以了. 解决方案二: htttprequest 效率低 解决方案三: 托管调用非托管的DLL编写C++非托管DLL以

对.Net 垃圾回收的C#编程相关方面(Finalize 和Dispose(bool disposing)和 Dispose())的一些理解体会

编程 Finalize 和Dispose(bool disposing)和 Dispose() 的相同点: 这三者都是为了释放非托管资源服务的. Finalize 和 Dispose() 和Dispose(bool disposing)的不同点: Finalize是CRL提供的一个机制, 它保证如果一个类实现了Finalize方法,那么当该类对象被垃圾回收时,垃圾回收器会调用Finalize方法.而该类的开发者就必须在Finalize方法中处理 非托管资源的释放. 但是什么时候会调用Finali

C#技术漫谈之垃圾回收机制(GC)

GC的前世与今生 虽然本文是以.net作为目标来讲述GC,但是GC的概念并非才诞生不久.早在1958年,由鼎鼎大名的图林奖得主John McCarthy所实现的Lisp语言就已经提供了GC的功能,这是GC的第一次出现.Lisp的程序员认为内存管理太重要了,所以不能由程序员自己来管理. 但后来的日子里Lisp却没有成气候,采用内存手动管理的语言占据了上风,以C为代表.出于同样的理由,不同的人却又不同的看法,C程序员认为内存管理太重要了,所以不能由系统来管理,并且讥笑Lisp程序慢如乌龟的运行速度.

.NET 垃圾回收与内存泄漏

原文:.NET 垃圾回收与内存泄漏 > 前言相信大家一定听过,看过甚至遇到过内存泄漏.在 .NET 平台也一定知道有垃圾回收器,它可以让开发人员不必担心内存的释放问题,因为它会自定管理内存.但是在 .NET 平台下进行编程,绝对不会发生内存泄漏的问题吗?答案是否定的,就算有了自动内存管理的垃圾回收器,也会发生内存泄漏.本文就讨论下 .NET 平台的垃圾回收器是如何工作的,进而当我们在编写 .NET 程序时避免发生内存泄漏的问题. > 垃圾回收的基本概念"垃圾"指的是事先分配

.NET,你忘记了么?(二)——使用using清理非托管资源

我们都知道,垃圾回收可以分为Dispose和Finalize两类,关于这两者的区别已经太多了 ,一个是正常的垃圾回收GC所调用的方法,另外一个是终结器Finalizer,所调用的方法,在 Effective C#一书中,有着明确的建议是说使用IDispose接口来代替Finalize.原因是因为 Finalize终结会增加垃圾回收对象的代数,从而影响垃圾回收. 有了上述的原因,我们现在只来看使用IDispose接口的类. 在.NET中,绝大多数的类都是运行在托管的环境下,所以都由GC来负责回收,