Dotnet 不调用其终结器,即使对象超出范围也是如此.那么如何释放非托管资源呢?



我尝试使用以下代码

[DllImport("Core.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateNode();
[DllImport("Core.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void ReleaseNode(IntPtr handle);
class Node
{
IntPtr nativePtr;
public int id;
public Node(int i)
{
nativePtr = CreateNode();
id = i;
Debug.WriteLine("Constructed " + id);
}
~Node()
{
ReleaseNode(nativePtr);
Debug.WriteLine("Destructed " + id);
}
}
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
Node n = new Node(i);
} //this scope
}
}

在循环中创建Node类的每个对象for离开 for 循环作用域(注释为"此作用域"(后不会销毁。 仅当 Main 方法的作用域结束时调用它。 是否可以在 for 循环作用域结束时自动调用 ~Node?

在执行上述代码时,我在调试窗口中得到以下内容。

Constructed 0
Constructed 1
Constructed 2
Constructed 3
Constructed 4
Constructed 5
Constructed 6
Constructed 7
Constructed 8
Constructed 9
Destructed 9
Destructed 0
Destructed 8
Destructed 7
Destructed 6
Destructed 5
Destructed 4
Destructed 3
Destructed 2
Destructed 1

这表明首先构造的对象在最后一个被破坏。如果发生这种情况,当我循环运行数千个项目时会发生什么? 它会消耗我所有的内存吗?

如何完美释放非托管资源?

TL;DR:如果可能的话,摆脱终结器,只相信垃圾回收器会做正确的事情。

定型是不确定的。请务必了解对象不会超出范围;对象没有要开始的范围。变量超出范围,这不会触发任何内容。

通常,垃圾回收器只是在需要时运行。无法保证调用终结器的顺序或调用时间。(虽然您可以请求运行垃圾回收器,但这通常是一个坏主意,并且无论如何都没有什么保证。

不过,在你自己的类中有一个终结器几乎总是一个坏主意:它会延迟实际的垃圾收集,而且几乎总是有更好的方法来处理你在终结器中所做的任何事情。

C#(以及一般的.Net Framework(使用垃圾回收器来管理内存,所以你不需要担心这一点。如果你来自 c++,一开始可能会觉得有点奇怪,但 GC 做得很好。终结器由垃圾收集器调用,文档明确指出:

程序员无法控制何时调用终结器 因为这是由垃圾回收器确定的。

如果你有一个资源量很大的类,并且你想要控制何时释放资源,你应该使用IDisposableusing语句。

调用终结器由垃圾回收器完成。若要完美控制非托管资源,请使用一次性模式

class MyResource : IDisposable
{
~MyResource()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); // don't finalize after the object has already been disposed of
}
protected void Dispose(bool disposing)
{
if(disposing)
{
// TODO: Dispose managed resources
}
// TODO: Dispose unmanaged resources
}
}
// when using
using(var resource = new MyResource())
{
// ... use resource
} // when out of "using" scope, it will be disposed

最新更新