为什么我们已经有 finalizers 时还需要进行 dispose 的操作呢?

30 浏览
0 Comments

为什么我们已经有 finalizers 时还需要进行 dispose 的操作呢?

我听说过关于在finalizer和Dispose()方法中放置代码以处理非托管资源的建议。但我不明白的是,既然finalizer在GC发生时被调用,所以我们可以从技术上假设它一直被调用。在这种情况下,为什么还要处理对象的释放?我是不是漏掉了什么?

0
0 Comments

C#中为什么需要手动释放资源,而不是依赖于垃圾回收器的终结器?

在C#中,垃圾回收器(GC)是用于管理内存的重要组成部分。当对象不再被引用时,垃圾回收器会自动回收该对象所占用的内存。然而,有些资源不仅仅是内存,还包括文件句柄、数据库连接、网络连接等。这些资源需要在适当的时候进行释放,以免造成资源的浪费和系统的负担。垃圾回收器无法自动释放这些资源,因此需要手动进行释放。

C#中提供了一个IDisposable接口,用于释放非内存资源。通过实现 IDisposable 接口,在对象不再被使用时,可以显式地调用 Dispose 方法来释放所占用的资源。Dispose 方法可以在代码中的任意位置被调用,以便及时释放资源。使用 Dispose 方法可以避免使用垃圾回收器的终结器(Finalizer)。

为什么不直接依赖于终结器来释放资源呢?终结器是在对象被垃圾回收器回收时调用的方法,但是终结器存在两个显著的缺点:

1. 终结器的调用时间是不确定的,它是在垃圾回收器检测到对象可以被回收时才被调用的。这意味着在开发人员希望释放资源和实际释放资源之间可能存在很大的延迟。对于那些需要获取大量稀缺资源(资源容易被耗尽)或者资源维持使用代价很高的情况,这种延迟是无法接受的。

2. 当垃圾回收器需要调用一个终结器时,它必须推迟对象内存的回收,直到下一轮垃圾回收(终结器在回收之间运行)。这意味着对象的内存(以及它引用的所有对象)将会在更长的时间内不被释放。

为了在需要时及时释放资源并避免不确定的延迟,C#中推荐手动实现 Dispose 方法来释放非内存资源,而不是依赖于垃圾回收器的终结器。

0
0 Comments

为什么要在拥有终结器的情况下还需要手动释放对象呢?

因为你无法控制终结器何时运行。很可能垃圾收集器运行得不频繁,仅依靠终结器的程序可能因为缺乏资源(文件句柄、数据库连接)而崩溃。

最佳实践(可释放模式)将终结器作为备用方案,通常执行终结器被认为是需要修复的错误。

或者,如果终结器运行。有人给我提供一篇我在想的博客文章的链接:)

在这里找到了:blogs.msdn.com/b/oldnewthing/archive/2010/08/09/10047586.aspx

是的,没错,这是一个特例,但它显示了我们无法完全依赖终结器来实现资源释放逻辑。

0