从this主题,Dispose()
必须显式调用一次性对象。
Windows服务停止后会发生什么?这些对象使用的资源是否会自动释放?或者应该在服务停止之前处理它们:
public void Stop()
{
cancellationTokenSource.Cancel();
waitForAllTasksToExit();
cancellationTokenSource.Dispose();
}
“处理”是一种很好的做法,“当服务停止时,它们应该被释放”,这也是我的想法。但参考文档是否有具体的答案?
答案 0 :(得分:5)
这取决于“这些对象使用的资源”是什么。 Dispose
方法本身不会在进程退出时调用,但除了Dispose
之外,包含“非托管”资源的大多数对象也具有终结器。将在进程退出时调用Finalizer,但可能不会在进程崩溃时调用它。现在,在流程退出(或崩溃)the following发生时:
释放进程分配的所有资源。
所有内核对象都已关闭。
内核对象例如是文件句柄,套接字等。因此,即使进程崩溃并且终结器未运行(或根本没有终结器),操作系统仍将关闭文件或数据库\网络连接等内容。
您可能拥有更广泛的非托管资源定义。非托管意味着不受.NET Framework垃圾收集器管理。例如,如果我在创建某个对象时在磁盘上创建文件,并在放置此对象时删除此文件 - 您可能会说这也是“非托管”资源。操作系统不知道这样的资源,如果由于进程崩溃而没有实现终结器或终结器,它将不会被“清理”。
总而言之 - 如果对象实现IDisposable
- 甚至在进程退出之前处置它。您可能不知道该对象开发人员的意图,是否有终结器 - 所以最好在进程退出之前始终明确地处理它。
答案 1 :(得分:2)
@Evk已经给出了答案,但对我来说并不完全清楚。在对文档进行了广泛的搜索之后,我参考了文档编译了以下答案。
长答案:
当服务停止时,它的资源将被垃圾收集器释放。
那么实现IDisposable
的对象呢? unmanaged resources会被释放吗? 否即可。来自Dispose Pattern:
GC专门用于管理此类非托管资源,这意味着管理非托管资源的责任掌握在开发人员手中。
那么,非托管资源会发生什么?他们永远不会被释放吗?
还有机会
Object声明一个虚拟方法Finalize(也称为终结器),它在GC回收对象的内存之前由GC调用,并且可以被覆盖以释放非托管资源。
然而,这有一些drawbacks:
尽管documentation表示实现IDisposable.Dispose
的对象应该覆盖Finalize方法或将托管对象包装在SafeHandle中,以便在使用者忘记调用Dispose
时,非托管资源仍然被释放;我们仍然可能遇到麻烦。
From the Docs,仅当派生类型覆盖它时才调用Finalize
方法。
那么,如果开发人员没有实现上述2(Finalize
或SafeHandle
),该怎么办?然后我们遇到了一个问题,没有人可以释放无人资源(至少文档没有说)。
<强> TLDR 强>
可以释放资源,也可以不释放资源(取决于上述情况)。因此,在您服务的Stop
方法中处理所有一次性物品(尚未丢弃)。
答案 2 :(得分:0)
作为最佳实践,必须在可支配资源上明确调用Dispose()
。但是,当您停止Windows服务时,它会向所有基础进程(即您的.NET代码)发送控制消息,并停止或卸载所有AppDomain
。因此,所有使用的资源和内存应该基本上被释放