【发布时间】:2021-03-30 09:59:06
【问题描述】:
我有一个 .NET Core C# 类,它包装了一个非托管指针,它应该在程序退出时与其他资源清理一起被释放。但是,没有调用析构函数。我在调试和发布模式下都试过了。我看到 .NET Core 显然不能保证会运行析构函数,那么推荐的解决方法是什么? IMO 垃圾收集的主要目的是避免让开发人员跟踪引用,所以我觉得这种行为至少可以说令人惊讶。
From MSDN:在 .NET Framework 应用程序中(但不在 .NET Core 应用程序中),程序退出时也会调用终结器。
public Demo {
IntPtr _ptr;
public Demo()
{
Console.WriteLine("Constructor");
_ptr = /* P-invoke external function */
~Demo
{
Console.WriteLine("Destructor");
/*P-invoke ptr deletion */
}
}
public static void Main()
{
Demo demo = new Demo();
demo = null;
GC.Collect();
}
程序输出:
Constructor
<...>\Test.exe (process 7968) exited with code 0.
【问题讨论】:
-
您是否尝试将
Demo声明为静态字段:static Demo demo = new Demo();,然后将其设置为null并调用GC.Collect()?你的意思是在这里实现IDisposable? (什么版本的 .Net Core?) -
IMO 正在运行的终结器是一个错误。使用带有
IDisposable的using块,以保证尽可能地处理。请记住,灾难性故障始终是一个问题,例如Environment.FailFast、taskkill或电源故障 -
自动清理非托管资源是一个值得称赞的目标,但在 C# 和终结器中实现起来却是出了名的困难,而不是解决这个问题。他们绝对不能保证运行,这只是最大的努力。进一步阅读joeduffyblog.com/2005/04/08/…和viva64.com/en/b/0437和scale-tone.github.io/2018/04/13/…和codeproject.com/Articles/15360/…
-
除了演示代码,我在 20 年的 .NET 编程中从未编写过终结器(我从 C# 的 alpha 版本开始)。终结器很难正确编写,极难测试,即使您编写了它们,也确实不应该运行(您应该尽可能使用
IDisposable进行清理)。如果你有绝对要求,看SafeHandles