我的 .net 服务通过在 Main() 循环退出之前在 finally 块中调用 resourceName.Dispose() 来清理其所有非托管资源。
我真的必须这样做吗?
我认为我不能因为进程结束而泄漏任何资源是正确的吗?Windows 将关闭不再使用的所有句柄,对吗?
我的 .net 服务通过在 Main() 循环退出之前在 finally 块中调用 resourceName.Dispose() 来清理其所有非托管资源。
我真的必须这样做吗?
我认为我不能因为进程结束而泄漏任何资源是正确的吗?Windows 将关闭不再使用的所有句柄,对吗?
对象可以封装的资源类型没有限制IDisposable
。绝大多数被IDisposable
对象封装的资源都会在进程关闭时被操作系统清理掉,但有些程序可能会使用操作系统一无所知的资源。例如,需要底层数据库不支持的锁定模式的数据库应用程序可能会使用一个或多个表来跟踪“签出”的内容以及由谁“签出”。使用此类表“检查”资源的类可以确保其Dispose
方法,一切都被重新签入,但如果程序关闭而类没有机会清理表,则由该表保护的资源将悬空。由于操作系统不知道这些表中的任何一个是什么意思,所以它无法清理它们。
在那种特定情况下,跳过这个可能是可以的。
首先要了解的是,虽然结束进程本身应该足以清理大多数事情,但一些非托管资源可能会处于不良或未关闭状态。例如,您可能有一个按席位获得许可的应用程序,当应用程序关闭时,您需要在某处更新数据库记录以释放您的许可。如果进程错误地终止,则不会发生任何更新,并且您最终可能会将人们锁定在您的软件之外。仅仅因为您的进程终止并不是不进行清理的借口。
但是,在具有 IDisposable 模式的 .Net 世界中,您可以获得更多保障。当进程退出时,所有剩余的终结器都将运行。如果Dispose() 模式被正确实现(这是一个比它应该的更大的“如果”),终结器仍然在那里为他们的对象处理任何剩余的非托管资源......
但是,最好始终养成自己正确处理这些东西的习惯。FWIW,仅调用 .Dispose() 不足以正确执行此操作。您的 .Dispose() 调用必须包含在 finally 块中(包括通过using
语句获得的隐式 finally 块)。