有可能在程序退出时强制在.NETCore中运行C#终结器吗?

有可能在程序退出时强制在.NETCore中运行C#终结器吗?,c#,.net-core,C#,.net Core,我有一个.NET核心C#类,它包装了一个非托管指针,应该在程序退出时与其他资源清理一起释放它。但是,没有调用析构函数。我在调试和发布模式下都尝试过。我发现.NETCore显然不能保证析构函数能够运行,那么推荐的解决方法是什么呢?在我看来,垃圾收集的主要目的是避免开发人员跟踪引用,所以我觉得这种行为至少令人惊讶 :在.NET Framework应用程序中(但不在.NET核心应用程序中)程序退出时也会调用终结器 public Demo { IntPtr _ptr; public Demo

我有一个.NET核心C#类,它包装了一个非托管指针,应该在程序退出时与其他资源清理一起释放它。但是,没有调用析构函数。我在调试和发布模式下都尝试过。我发现.NETCore显然不能保证析构函数能够运行,那么推荐的解决方法是什么呢?在我看来,垃圾收集的主要目的是避免开发人员跟踪引用,所以我觉得这种行为至少令人惊讶

:在.NET Framework应用程序中(但不在.NET核心应用程序中)程序退出时也会调用终结器

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.
构造函数
\Test.exe(进程7968)已退出,代码为0。

需要进行更多更改以提高调用终结器的可能性

顺便说一句,终结器永远不能保证被调用。如果要保证资源释放,请在应用程序/方法/代码块退出之前实现
IDisposable
并调用
Dispose()
。此外,要在退出代码块之前保证调用
Dispose()
(即使应用程序崩溃,FailFast和StackOverflow除外),请使用
try finally
using
语句

这里有一个例子

公共类程序
{
静态void Main(字符串[]参数)
{
Console.WriteLine(“[main]Constructing”);
MyDisposable m=新MyDisposable(0);
方法(1);
Console.WriteLine(“[main]Disposing[object 0]”);
m、 处置();
Console.WriteLine(“[main]GC收集”);
GC.Collect();
GC.WaitForPendingFinalizers();
控制台写入线(“[main]Done”);
Console.ReadKey();
}
私有静态void MyMethod(int i)
{
新成立的第一期(i);;
}
}
公共类:IDisposable
{
私人内部id;
公共文件(int id)
{
_id=id;
WriteLine($“[object{u id}]构造”);
}
私有布尔=假;
公共空间处置()
{
处置(真实);
总干事(本);
}
受保护的虚拟void Dispose(bool disposing)
{
如果(!已处置)
{
如果(处置)
{
WriteLine($“[object{{u id}]Dispose by Dispose()”;
}
其他的
{
WriteLine($“[object{u id}]由~Finalizer处理”);
}
WriteLine($“[object{u id}]Disposed”);
这是真的;
}
其他的
WriteLine($“[object{{u id}]已被释放!”);
}
~MyDisposable()
{
处置(虚假);
}
}
输出

[main]正在构建
已构造[0]对象
[对象1]构造
[main]正在处理[object 0]
[对象0]按Dispose()处理
[对象0]已释放
[主]GC收集
[对象1]由~Finalizer处理
[对象1]已处置
[主要]完成

有些人说:。

需要更多的更改来提高调用终结器的可能性

顺便说一句,终结器永远不能保证被调用。如果要保证资源释放,请在应用程序/方法/代码块退出之前实现
IDisposable
并调用
Dispose()
。此外,要在退出代码块之前保证调用
Dispose()
(即使应用程序崩溃,FailFast和StackOverflow除外),请使用
try finally
using
语句

这里有一个例子

公共类程序
{
静态void Main(字符串[]参数)
{
Console.WriteLine(“[main]Constructing”);
MyDisposable m=新MyDisposable(0);
方法(1);
Console.WriteLine(“[main]Disposing[object 0]”);
m、 处置();
Console.WriteLine(“[main]GC收集”);
GC.Collect();
GC.WaitForPendingFinalizers();
控制台写入线(“[main]Done”);
Console.ReadKey();
}
私有静态void MyMethod(int i)
{
新成立的第一期(i);;
}
}
公共类:IDisposable
{
私人内部id;
公共文件(int id)
{
_id=id;
WriteLine($“[object{u id}]构造”);
}
私有布尔=假;
公共空间处置()
{
处置(真实);
总干事(本);
}
受保护的虚拟void Dispose(bool disposing)
{
如果(!已处置)
{
如果(处置)
{
WriteLine($“[object{{u id}]Dispose by Dispose()”;
}
其他的
{
WriteLine($“[object{u id}]由~Finalizer处理”);
}
WriteLine($“[object{u id}]Disposed”);
这是真的;
}
其他的
WriteLine($“[object{{u id}]已被释放!”);
}
~MyDisposable()
{
处置(虚假);
}
}
输出

[main]正在构建
已构造[0]对象
[对象1]构造
[main]正在处理[object 0]
[对象0]按Dispose()处理
[对象0]已释放
[主]GC收集
[对象1]由~Finalizer处理
[对象1]已处置
[主要]完成
一些人读到:。

官员 国家:

如果类型使用非托管资源,则应执行以下操作:

实现dispose模式。(……)

如果您类型的使用者忘记调用Dispose,请提供释放非托管资源的方法。有两种方法可以做到这一点:

  • 使用安全句柄包装非托管资源。这是推荐的技术。安全句柄派生自System.Runtime.InteropServices.SafeHandle抽象类,并包含一个健壮的Finalize方法。使用安全句柄时,只需实现ID