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