在Windows服务停止之前是否应丢弃一次性对象?

时间:2017-10-10 12:44:03

标签: c# dispose

this主题,Dispose()必须显式调用一次性对象。

Windows服务停止后会发生什么?这些对象使用的资源是否会自动释放?或者应该在服务停止之前处理它们:

public void Stop()
{
    cancellationTokenSource.Cancel();
    waitForAllTasksToExit();
    cancellationTokenSource.Dispose();
}

“处理”是一种很好的做法,“当服务停止时,它们应该被释放”,这也是我的想法。但参考文档是否有具体的答案?

3 个答案:

答案 0 :(得分:5)

这取决于“这些对象使用的资源”是什么。 Dispose方法本身不会在进程退出时调用,但除了Dispose之外,包含“非托管”资源的大多数对象也具有终结器。将在进程退出时调用Finalizer,但可能不会在进程崩溃时调用它。现在,在流程退出(或崩溃)the following发生时:

  

释放进程分配的所有资源。

     

所有内核对象都已关闭。

内核对象例如是文件句柄,套接字等。因此,即使进程崩溃并且终结器未运行(或根本没有终结器),操作系统仍将关闭文件或数据库\网络连接等内容。

您可能拥有更广泛的非托管资源定义。非托管意味着不受.NET Framework垃圾收集器管理。例如,如果我在创建某个对象时在磁盘上创建文件,并在放置此对象时删除此文件 - 您可能会说这也是“非托管”资源。操作系统不知道这样的资源,如果由于进程崩溃而没有实现终结器或终结器,它将不会被“清理”。

总而言之 - 如果对象实现IDisposable - 甚至在进程退出之前处置它。您可能不知道该对象开发人员的意图,是否有终结器 - 所以最好在进程退出之前始终明确地处理它。

答案 1 :(得分:2)

@Evk已经给出了答案,但对我来说并不完全清楚。在对文档进行了广泛的搜索之后,我参考了文档编译了以下答案。

长答案:

当服务停止时,它的资源将被垃圾收集器释放。

那么实现IDisposable的对象呢? unmanaged resources会被释放吗? 即可。来自Dispose Pattern

  

GC专门用于管理此类非托管资源,这意味着管理非托管资源的责任掌握在开发人员手中。

那么,非托管资源会发生什么?他们永远不会被释放吗?

还有机会

  

Object声明一个虚拟方法Finalize(也称为终结器),它在GC回收对象的内存之前由GC调用,并且可以被覆盖以释放非托管资源。

然而,这有一些drawbacks

  1. 在GC检测到有资格收集后,在一段不确定的时间后调用对象的终结器。
  2. 终结器在集合之间运行,因此在下一轮垃圾收集之前,对象的内存不会被释放。
  3. 尽管documentation表示实现IDisposable.Dispose的对象应该覆盖Finalize方法或将托管对象包装在SafeHandle中,以便在使用者忘记调用Dispose时,非托管资源仍然被释放;我们仍然可能遇到麻烦。

    From the Docs,仅当派生类型覆盖它时才调用Finalize方法。

    那么,如果开发人员没有实现上述2(FinalizeSafeHandle),该怎么办?然后我们遇到了一个问题,没有人可以释放无人资源(至少文档没有说)。

    <强> TLDR

    可以释放资源,也可以不释放资源(取决于上述情况)。因此,在您服务的Stop方法中处理所有一次性物品(尚未丢弃)。

答案 2 :(得分:0)

作为最佳实践,必须在可支配资源上明确调用Dispose()。但是,当您停止Windows服务时,它会向所有基础进程(即您的.NET代码)发送控制消息,并停止或卸载所有AppDomain。因此,所有使用的资源和内存应该基本上被释放