在没有共享 COM 对象的情况下使用 COM STA 或 MTA?
Use COM STA or MTA Without Shared COM Objects?
This thread 很好地解释了 COM 的 STA 与 MTA,但是它没有解决如何为此编写代码或何时使用其中一个或另一个的问题,而仅讨论了有关正在使用的 COM 单元的技术细节是否通过线程安全对象。我敢打赌大多数用户只是想知道如何通过 COM 使用 Win API 而无需在多个线程之间共享任何 COM 对象。
如果您的 COM 对象不在线程之间共享,并且您的代码使用多个线程或单个线程,每个线程都有自己的 COM 对象实例,none 个共享对象,您是否应该始终使用 STA ?这取决于您使用的对象吗?如果您不总是为此使用 STA,您什么时候使用 MTA?在这种情况下,您是否需要消息泵?
在我的例子中,我使用工作线程中的 Task Scheduler API (ITaskService) and the Shell Links/Create Shortcut API (IShellLink) from the main GUI thread (using the Qt Framework), and the File Operation API (IFileOperation) and the 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.
查看全部,这个link:INFO: Calling Shell Functions and Interfaces from a Multithreaded Apartment
我怀疑文档真正想说的是:
- 实施 IFileOperation 的 class 不是线程安全的
- 它的 ThreadingModel 已在注册表中声明 "apartment",如果从 MTA 线程访问,将产生编组开销。
在我们的应用程序中,在主 STA 线程上使用了 ITaskScheduler。我们在具有自己的消息泵的后台 STA 线程上使用 IFileOperation。
其他一些我觉得很有用的link:
This thread 很好地解释了 COM 的 STA 与 MTA,但是它没有解决如何为此编写代码或何时使用其中一个或另一个的问题,而仅讨论了有关正在使用的 COM 单元的技术细节是否通过线程安全对象。我敢打赌大多数用户只是想知道如何通过 COM 使用 Win API 而无需在多个线程之间共享任何 COM 对象。
如果您的 COM 对象不在线程之间共享,并且您的代码使用多个线程或单个线程,每个线程都有自己的 COM 对象实例,none 个共享对象,您是否应该始终使用 STA ?这取决于您使用的对象吗?如果您不总是为此使用 STA,您什么时候使用 MTA?在这种情况下,您是否需要消息泵?
在我的例子中,我使用工作线程中的 Task Scheduler API (ITaskService) and the Shell Links/Create Shortcut API (IShellLink) from the main GUI thread (using the Qt Framework), and the File Operation API (IFileOperation) and the 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.
查看全部,这个link:INFO: Calling Shell Functions and Interfaces from a Multithreaded Apartment
我怀疑文档真正想说的是:
- 实施 IFileOperation 的 class 不是线程安全的
- 它的 ThreadingModel 已在注册表中声明 "apartment",如果从 MTA 线程访问,将产生编组开销。
在我们的应用程序中,在主 STA 线程上使用了 ITaskScheduler。我们在具有自己的消息泵的后台 STA 线程上使用 IFileOperation。
其他一些我觉得很有用的link: