【问题标题】:What's the best way to signal threads that sleep or block to stop?向睡眠或阻塞的线程发出信号以停止的最佳方式是什么?
【发布时间】:2010-09-26 00:02:59
【问题描述】:

我有一项服务需要关闭和更新。我在两种不同的情况下遇到了困难:

  1. 我有一些线程会长时间休眠。显然我等不及他们醒来完成关闭服务。我想使用一个 AutoResetEvent,它在睡眠间隔结束时由某个控制器线程设置(只需每两秒检查一次或其他东西),并在 OnClose 时间立即触发它。有没有更好的方法来促进这一点?

  2. 我有一个线程调用阻塞方法调用(我无法修改)。你如何通知这样一个线程停止?

【问题讨论】:

    标签: multithreading winapi windows-services signals


    【解决方案1】:
    1. 我不确定我是否正确理解了您的第一个问题,但您是否考虑过使用 WaitForSingleObject 替代 Sleep?您可以指定超时以及要等待的对象,因此如果您希望它早点唤醒,只需向该对象发出信号即可。

    2. “调用阻塞线程”到底是什么意思?或者你的意思是阻塞电话?一般来说,没有办法在不强制终止线程的情况下中断线程。但是,如果调用是系统调用,可能可以通过使调用失败来返回控制权,例如。取消 I/O 或关闭关联的句柄。

    【讨论】:

    • 对不起,是的,我的意思是阻塞方法调用。
    • 究竟是什么电话?可能有办法打断它。
    • 这是对 NamedPipeServerStream.WaitForConnection() 的调用。我将切换到异步使用流。这只是一个很大的痛苦,除非有人知道一种与超时同步的方法。受您的 WaitForSingleObject 建议的启发,我还将使用 AutoResetEvent 的 WaitOne 超时。谢谢!
    • 对 OP 有帮助为时已晚,但对于未来的读者来说,这种特殊情况有一个简单的解决方案:自己连接到命名管道。
    【解决方案2】:

    对于 1. 您可以使用 SleepEx 而不是 Sleep 使您的线程进入可中断的睡眠状态。一旦他们得到这个关闭启动(使用 QueueUserApc 从您的终止逻辑启动),您可以使用来自 SleepEx 的返回码检测它发生并相应地终止这些线程。这类似于使用 WaitForSingleObject 的建议,但您不需要另一个仅用于终止关联线程的每个线程句柄。

    返回值为零,如果 指定的时间间隔已过期。

    返回值为WAIT_IO_COMPLETION 如果函数由于一个或 更多 I/O 完成回调 职能。这只有在 bAlertable 为 TRUE,如果线程 调用 SleepEx 函数的是 调用的同一线程 扩展 I/O 功能。

    对于 2.,这是一个艰难的问题,除非您有权访问该线程中使用的某些资源,这些资源可能导致阻塞调用以调用线程可以干净地处理它的方式中止。您可能只需要使用TerminateThread(可能这应该是您在退出进程之前做的最后一件事)来执行代码以终止该线程,然后看看在测试中会发生什么。

    【讨论】:

      【解决方案3】:

      一个简单可靠的解决方案是杀死服务进程。毕竟,进程是操作系统的内存安全抽象,因此您可以安全地终止一个进程而不考虑进程内部状态 - 当然,如果您的进程正在通信或摆弄外部状态,那么所有的赌注都没有......

      此外,您可以实施操作系统本身通常执行的解决方案:一个警告信号要求进程尽可能清理(设置标志并优雅退出可以优雅停止的内容),然后如果进程强制终止不会自行退出(这会结束令人讨厌的事情,例如阻塞 I/O)。

      所有服务都应该建立在强制终止无害的情况下,因为这些进程是系统管理的,并且可能会被诸如重启之类的事情终止 - 即,您的服务理想情况下应该允许这样做而不无论如何都会损坏存储。

      哦,还有最后一个警告; Windows 服务可能共享一个进程(我认为是为了提高效率,尽管我认为这是一种可以避免的优化),所以如果你走这条路,你要确保你的服务与其他服务共享一个进程服务。您可以通过将选项 SERVICE_WIN32_OWN_PROCESS 传递给 ChangeServiceConfig 来确保这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-28
        • 2014-05-15
        • 1970-01-01
        相关资源
        最近更新 更多