嗨,我是 COM 初学者。我想在 STA 和 MTA 模式下测试 COM dll。我的第一个问题是:COM 对象是否可能同时支持 STA 和 MTA?
现在我想象下面的 STA 代码片段:
// this is the main thread
m_IFoo;
CoInitializeEx(STA); // initialize COM in main thread
CreateInstance(m_IFoo);
m_IFoo->Bar();
CreateThread(ThreadA);
// start ThreadA
// this is secondary thread
ThreadA()
{
CoInitializeEx(STA);
m_IFoo->Buz(); // call m_IFoo's method directly
}
这段代码可以工作吗?我是否遗漏了任何基本的东西?我知道主线程需要一个窗口消息循环来执行来自其他线程的调用。我需要做些什么吗?
现在我继续测试 MTA。如果我只是将上面代码中的“STA”替换为“MTA”,可以吗?
另一个问题是:由于带有GUI的线程必须是STA,所以我无法在GUI线程中初始化和测试MTA?
提前致谢,并为我对 COM 和线程的幼稚感到抱歉。
最佳答案
您的代码不是合法的 COM,因为您将指针直接从一个 STA 传递到另一个 STA,而 COM 不允许这样做。
在COM中,接口(interface)指针具有“公寓亲和性”,它们只能在公寓内使用。要将指针从一个 STA 传递到另一个 STA,或者在 STA 和 MTA 之间传递,您必须将指针“编码”到一个安全的表示形式,然后由接收线程取消编码。
最简单的方法是使用 Global Interface Table ;您在一个线程中向其注册接口(interface)并返回一个 DWORD,然后在另一个线程中使用它来获取另一个线程可以使用的接口(interface)版本。
如果两个线程都是 MTA,则可以避免这样做。虽然 STA 是每个线程一个 - 每个 STA 线程都有自己的公寓 - MTA 由所有 MTA 线程共享。这意味着 MTA 线程可以在它们之间自由传递 COM 指针。 (但如果将指针传递给 STA 线程或从 STA 线程传递指针,它们仍然需要编码(marshal)。)
一般来说,您不会在 STA 或 MTA 之间更改代码,通常一开始就决定一次。如果线程有UI,那么它需要消息循环,并且通常是STA。如果没有 UI,您可能会决定使用 MTA。但是,一旦您做出决定并编写代码,以后就很少会更改为另一个,因为选择一个或另一个具有影响代码的不同要求和假设;从 STA 更改为 MTA,反之亦然,您必须仔细检查代码,看看是否需要更改指针分配等内容。
关于multithreading - 关于COM多线程和STA/MTA的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6253692/