【问题标题】:How to dispose BackgroundWorkers the right way如何正确处理 BackgroundWorkers
【发布时间】:2010-05-31 22:36:47
【问题描述】:

我有一个运行 BackgroundWorker 的 Windows 服务,我想知道当我停止我的 Windows 服务时我是否在做正确的事情。

是否足够:

  1. BackgroundWorker1_DoWork方法完成(我现在有一个while循环,做一些任务)
  2. 将保存对BackgroundWorker 的引用的变量设置为null

我需要调用某种Dispose() 方法吗(与Timer 类具有Timer.Dispose(); 相同)?

【问题讨论】:

标签: c# timer backgroundworker


【解决方案1】:

坦率地说,当您停止 Windows 服务时,这并不重要。您的 win32 进程已终止,因此清理 IDisposables 并不是绝对必要的。任何非托管资源都会有一个仍会运行的终结器。

也就是说,有一个类级别的后台工作程序在 e 服务类处理时被释放是很正常的。没必要,但干净总是好的。

【讨论】:

  • 当您停止 Windows 服务时,SCM(服务控制管理器)将调用您的停止界面并等待默认时间段,然后才会杀死您 - 我认为默认情况下是 15 秒。在这段时间内,您可以彻底关闭您的服务。
【解决方案2】:

由于BackgroundWorker 实现了IDisposable,所以你应该在完成后处理它。

您提到这是在 Windows 服务中,所以这里有一些东西可以发挥作用。当您停止 Windows 服务时,您有大约 30 秒的时间从 ServiceBase 实现中的 OnStop 方法返回。如果您没有在这段时间内返回,Windows 会向用户报告它无法停止服务。您应该做的是向BackgroundWorker 发出信号,告知您需要它停止(使用CancelAsync 机制),处置工作人员,然后退出。但是,由于您要停止服务,所以 整个进程无论如何都会终止,包括其中运行的所有线程,这并不重要。

如果您按照您说的做并等待工作人员完成(在OnStop 方法中),您的服务可能会在用户看来好像它已挂起,因为 Windows 会说它无法停止它,并且该进程仍将运行。

【讨论】:

    【解决方案3】:

    正确的方法是让工作线程干净地完成它正在做的事情。

    这通常可以通过共享标志\waithandle\whatever 来实现洗牌并蒸发。工作线程应该定期检查“标志”以查看它是否需要退出(例如在您的循环中),并且主服务线程可以在需要关闭时发出标志信号。然后主线程等待工作线程退出,例如通过在工作线程上调用 join。

    【讨论】:

      【解决方案4】:

      BackgroundWorker 是 IDisposable,因此您应该在不再需要时将其丢弃。

      BackgroundWorkers 还有一个 CancelAsync 方法,可将 CancellationPending 属性更改为 true。您可以在 DoWork 函数中检查它,以便阻止它运行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多