【发布时间】:2019-09-10 04:08:41
【问题描述】:
This thread 非常擅长解释 COM 的 STA 与 MTA,但它没有解决如何编写代码或何时使用其中一个,而仅讨论了线程安全使用的 COM 单元的技术细节对象与否。我敢打赌,大多数用户只是想知道如何通过 COM 使用 Win API,而无需在多个线程之间共享任何 COM 对象。
如果您的 COM 对象不在线程之间共享,并且您的代码使用多个线程或单个线程,每个线程都有自己的 COM 对象实例,并且没有共享对象,您是否应该始终使用 STA?这取决于您使用的对象吗?如果您不总是使用 STA,那么您何时使用 MTA?在这种情况下,您是否需要消息泵?
在我的例子中,我使用来自主 GUI 线程(使用 Qt 框架)的 Task Scheduler API (ITaskService) 和 Shell Links/Create Shortcut API (IShellLink),以及来自 a工作线程。
在初始化和使用 COM 对象之前,我从每个线程调用 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);,之后调用 CoUninitialize();。这是 COM 的正确用法吗?在没有工作线程的情况下使用来自主 GUI 线程的 COM 对象是否同样适用?
【问题讨论】:
-
在理想世界中,作为线程所有者,您不应该关心(抛开跨单元调用可能存在的性能问题)您使用的 COM 服务器是 STA 还是 MTA。这基本上就是所有这些 COM 线程的全部意义,它应该是一个 功能 而不是负担......不幸的是,大多数 shell 对象(和其他......)只是不提供必要的对象(tlb,代理等)来编组公寓之间的调用(确切的原因对我来说仍然是模糊的,除了微软的兼容性问题......)。所以你必须关心...对于这些对象,无论是否共享,你必须创建一个 STA 线程。
-
选择STA是一个承诺,穿越你的心希望死。永远不要阻塞和泵送消息循环,您知道何时要这样做。您希望可以撒谎,并希望在谎言造成麻烦时死去。结果通常没问题,您的程序将死锁,或者您希望引发的事件不会触发。不能保证,也不容易诊断,这是他们在您致电 Microsoft 支持时快速让您挂断电话的方式。或者。如果你打算在 shell 接口上撒谎,那么你还需要在 Win7 上进行测试。
-
@Simon 那么始终使用 STA 是否安全?
-
如果您使用的是 Shell 对象,这可能是最安全的方式。但没有任何事情可以保证。
标签: c++ multithreading winapi com