我有一个本机的Visual C NT服务.当服务启动时,它的线程调用CoInitialize(),它将线程附加到STA – 服务线程通过COM接口使用MS
XML.
当服务收到SERVICE_CONTROL_STOP时,它会在消息队列中发布消息,然后检索该消息并调用OnStop()处理程序.处理程序清理东西并调用CoUnitialize().大部分时间它都可以正常工作,但偶尔会在后面调用挂起.我无法稳定地重现这种行为.
我用谷歌搜索了一段时间,发现了以下可能的解释:
>未能释放所有拥有的COM对象
> repeatedly calling CoInitializeEx()
/CoUnitialize()
for attaching to MTA
> failing to dispatch messaged in STA threads
第一个是不太可能的 – 使用MSXML的代码经过了充分测试和分析,它使用智能指针来控制对象的生命周期,因此泄漏对象的可能性很小.
第二个看起来不是可能的原因.我附加到STA,不要重复调用这些函数.
第三个看起来或多或少.当线程正在处理消息时,它不再运行消息循环 – 它已经在循环内部.我想这可能就是原因.
后者是这个问题的可能原因吗?我应该考虑其他什么原因?如何轻松解决此问题?
解决方法
在处理SCM消息的线程中不要做任何后果,它处于一个奇怪的魔法环境中 – 你必须尽可能快地回答SCM的请求而不采取任何阻止操作.告诉它你需要额外的时间通过STOP_PENDING,排队另一个线程进行真正的清理,然后立即完成SCM消息.
至于CoUninitialize,只需附加WinDbg并转储所有线程 – 死锁很容易诊断(也许不能修复!),你已经在堆栈中有犯罪的所有各方.