在Using块内调用Environment.Exit()

12

如果我有一个控制台应用程序,其中的代码类似于:

using (DisposableObject object = new DisposableObject())
{
   if (a condition)
     Environment.Exit(0);

   // Do Stuff
}

我的对象会被正确清理吗?还是线程在对象被清理之前就终止了?


请注意,如果您正在关闭应用程序,即使对象未被Dispose,也不会出现内存泄漏(因为进程保护的内存空间在进程终止时完全释放)。 如果Disposal具有更持久的副作用(例如提交到数据库或超出进程范围的某些内容),其他问题可能会发生。 - Dan Bryant
1
@DanBryant 一个未发布的资源不会泄漏托管内存。如果未托管的资源是未托管内存(可能是由于与未管理语言的交互),那么您可能会有未释放的内存。 - Servy
我实际上是在一个 SqlConnection 上使用它,但这个 using 块嵌套在另外两个块中(SharePoint 对象)。我只是想确保 Dispose() 方法会被调用,因为不释放 SP 对象会在日志中生成错误。 - RJ Cuthbertson
嗯...也许是时候重新考虑使用Environment.Exit()的方法了? - code4life
我总是可以抛出一个异常。 - RJ Cuthbertson
2个回答

11

当应用程序终止时,所有托管内存都将被释放。

生成的finally块不会执行,因此任何Dispose方法都不会被调用,所以任何非托管资源可能都不会被释放。

请参见不要盲目依赖Finalizer


“// Do Stuff” 代码会被执行吗?Environment.Exit(0); 究竟是做什么的? - Olivier Jacot-Descombes
“// Do Stuff” 不会被执行。“Environment.Exit(0)” 结束线程并从主函数返回0。 - RJ Cuthbertson
@OlivierJacot-Descombes - // Do Stuff 不会执行。该调用只是终止进程(返回错误代码 - 传入的 int)。 - Oded
1
@rj - 你担心内存泄漏。一般情况下这并没有太多意义,终止的进程不会泄漏内存。IDisposable也与内存无关。你唯一需要担心的是极小的一个角落情况,即类有一个finalizer并且在清理时与Dispose()不同。不要编写finalizers。 - Hans Passant
1
我没有写入日志。它们是SharePoint对象。如果您不处理,SharePoint会为您处理,但会在日志中生成一个错误,指出您没有正确处理。我正在进行测试(试图强制执行此行为)。 - RJ Cuthbertson
显示剩余5条评论

1

当应用程序退出时,操作系统知道的资源通常会被清理。操作系统不知道的资源通常不会被清理。

例如,一些使用数据库并需要实现与数据库服务器直接支持的锁定范例不同的程序可能会使用一个或多个“LockedResources”表来跟踪应该锁定哪些资源。需要获取资源的代码将锁定“LockedResources”表,更新它以显示需要锁定哪些资源,然后释放它;即使应用程序需要长时间持有真正的资源,对“LockedResource”表的操作通常也会非常快速(因此“LockedResource”表仅会短暂锁定)。但是,如果应用程序在“LockedResources”表表示拥有某个资源时执行Environment.Exit,操作系统将不知道如何更新“LockedResources”表以取消这种所有权。

一般而言,像数据库应用程序这样的东西应该被设计成强健的,即使客户端应用程序意外关闭也不会出现问题。例如,可以有一个活动客户端表,每个活动客户端都持有一个记录锁定自身身份的记录。如果想要使用资源的客户端注意到“LockedResources”表已被其他客户端选中,前一个客户端可以检查以确保后一个客户端在“活动客户端”表中的条目仍然被锁定。如果没有,它可以判断准备使用的客户端已经死亡并采取适当的措施(认识到已死亡的客户端可能已经把资源留在了错误的状态下)。另一方面,虽然数据库应该被设计成在客户端意外死亡时具有强壮性,但并不意味着它们总是如此。资源的放弃并不是好事,即使通常是可以幸存的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接