异步停止 Windows 服务

3
我正在尝试控制应用程序中的一个服务。通过StartService(MSDN)启动服务工作正常,服务需要大约10秒钟才能启动,但在调用StartService后,它立即将控制权交回主应用程序。
然而,当使用ControlService(MSDN)停止服务时 - 据我所知,没有StopService - 它会阻塞主应用程序直到服务停止,这需要大约10秒钟的时间。
Start: StartServiceW( handle, 0, NULL)
Stop: ControlService( handle, SERVICE_CONTROL_STOP, status )

有没有一种非阻塞/异步停止Windows服务的方法?

2
你试过从线程中调用它吗?将阻塞调用转换为非阻塞的经典方法... - Christian Stieber
我不知道怎么做,但是sc命令允许您停止服务而不会被阻止。尝试在那里查找有趣的API函数。 - wilx
有一个特定的服务表现出这种情况,还是所有服务都是这样?我猜测问题所在的服务没有正确响应停止请求。 - Harry Johnston
这是一个服务。该服务需要约10秒钟进行清理/正确关闭,在此期间ControlService会阻塞。另一方面,该服务需要约10秒钟启动,但StartService不会阻塞。 - OnTheFly
3个回答

1
我建议您在新线程中停止该服务。这样可以消除主线程的阻塞。

1

SCM进程以串行方式控制请求。如果任何服务正在处理控制请求,则ControlService()将被阻塞,直到SCM可以处理新请求。这在文档中已经说明:

SCM以串行方式处理服务控制通知-它会等待一个服务完成处理服务控制通知后再发送下一个。因此,如果任何服务正在处理控制代码,则对ControlService的调用将阻塞30秒钟。如果繁忙的服务在超时到期时仍未从其处理程序函数返回,则ControlService失败并显示ERROR_SERVICE_REQUEST_TIMEOUT。


谢谢,我已经阅读了。除了我的控制请求之外,没有其他的控制请求,所以我不认为这适用于这里,对吗? - OnTheFly
如果任何服务正在处理控制代码,对ControlService的调用将会阻塞30秒钟,而不仅仅是您的服务。 - Remy Lebeau

1
该服务在其控制处理程序中进行清理。对于只需要花费一小部分时间退出的服务来说,这是可以接受的,但是对于需要花费十秒钟的服务,应该明确设置STOP_PENDING状态,然后异步进行清理。
如果这是您自己的服务,您应该纠正这个问题。我会从确保所有清理都是必要的开始;例如,在停止之前没有必要释放内存(除非服务与其他服务共享进程)。如果清理确实无法快速完成,请启动一个单独的线程(或者向主线程发出信号)来执行服务关闭,并将服务状态设置为STOP_PENDING。
如果这是别人的服务,唯一的解决方案是从单独的线程或子进程中发出停止请求。

谢谢。我已经设置了SERVICE_STOP_PENDING,但是ControlService一直阻止,直到SERVICE_STOPPED。太糟糕了... - OnTheFly
服务控制例程在将状态设置为SERVICE_STOP_PENDING后是否退出?你能展示一下代码吗? - Harry Johnston

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接