This thread非常擅长解释 COM 的 STA 与 MTA,但是它没有解决如何为此编写代码或何时使用其中一个或另一个的问题,而只是讨论有关线程安全对象是否使用 COM 单元的技术细节。我敢打赌,大多数用户只是想知道如何通过 COM 使用 Win API,而无需在多个线程之间共享任何 COM 对象。
如果您的 COM 对象不在线程之间共享,并且您的代码使用多个线程或单个线程,每个线程都有自己的 COM 对象实例,没有任何对象共享,您是否应该始终使用 STA?这取决于您使用的对象吗?如果您不总是为此使用 STA,您什么时候使用 MTA?在这种情况下,您是否需要消息泵?
在我的例子中,我使用 Task Scheduler API (ITaskService) 和 Shell Links/Create Shortcut API (IShellLink) 来自主 GUI 线程(使用 Qt 框架),以及 File Operation API (IFileOperation) 和 Volume Shadow Copy Service API来自工作线程。
在初始化和使用 COM 对象之前,我从每个线程调用 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
,之后调用 CoUninitialize();
。这是 COM 的正确用法吗?在没有工作线程的情况下,使用来自主 GUI 线程的 COM 对象是否同样适用?
最佳答案
要对您通过 CoCreateInstance 实例化的对象进行出站 COM 调用,STA 应该足够好,并且对于您的 GUI 线程(具有 GetMessage/DispatchMessage 循环的线程)来说几乎是必须的。
当托管您自己的线程安全 COM 对象时,MTA 开始变得相关,这些对象预计会从其他进程调用。
The documentation for IFileOperation声明如下:
IFileOperation can only be applied in a single-threaded apartment (STA) situation. It cannot be used for a multithreaded apartment (MTA) situation. For MTA, you still must use SHFileOperation.
查看全部,此链接:INFO: Calling Shell Functions and Interfaces from a Multithreaded Apartment
我怀疑文档真正想说的是:
- 实现 IFileOperation 的类不是线程安全的
- 它的 ThreadingModel 在注册表中被声明为“单元”,如果从 MTA 线程访问,将产生编码开销。
在我们的应用程序中,在主 STA 线程上使用了 ITaskScheduler。我们在具有自己的消息泵的后台 STA 线程上使用 IFileOperation。
其他一些我觉得很有用的链接:
关于c++ - 在没有共享 COM 对象的情况下使用 COM STA 或 MTA?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57863927/