2

嗨,我是 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”,它会起作用吗?</p>

另一个问题是:作为带有 GUI 的线程必须是 STA,我不能在 GUI 线程中初始化和测试 MTA?

在此先感谢并为我对 COM 和线程的幼稚感到抱歉。

4

2 回答 2

4

您的代码不是合法的 COM,因为您将指针直接从一个 STA 传递到另一个,这是 COM 不允许的。

在 COM 中,接口指针具有“公寓亲和性”,它们只能在公寓内使用。要将指针从一个 STA 传递到另一个,或在 STA 和 MTA 之间传递,您必须将指针“编组”到安全表示,然后由接收线程解组。

最简单的方法是使用全局接口表;你在一个线程中注册接口并取回一个 DWORD,然后在另一个线程中使用它来取回另一个线程可以使用的接口版本。

如果两个线程都是 MTA,则可以避免这样做。虽然 STA 是每个线程一个 - 每个 STA 线程都有自己的 aparment - MTA 由所有 MTA 线程共享。这意味着 MTA 线程可以在它们之间自由地传递 COM 指针。(但如果向 STA 线程传递指针或从 STA 线程传递指针,它们仍然需要编组。)

一般来说,您不会在 STA 或 MTA 之间更改代码,通常一开始就决定一次。如果线程有 UI,那么它需要一个消息循环,通常是 STA。如果没有 UI,您可能会决定使用 MTA。但是,一旦您做出决定并编写代码,以后就很少更改为另一个,因为选择一个或另一个具有影响代码的不同要求和假设;从 STA 更改为 MTA 或反之亦然,您必须仔细检查代码并查看是否需要更改指针分配等内容。

于 2011-06-06T22:06:47.307 回答
2

能够从“MTA”切换到“STA”以及这种切换的后果将取决于对象在系统注册表中的注册方式。为了让对象在不编组的情况下“支持”这两种情况,它必须ThreadingModel设置为Both.

请看这个很好的答案-Both意思是“Free或者Apartment取决于调用者如何初始化 COM”。这正是你想要的。

至于使用“STA”模式 - 是的,tread 对象所属的将必须通过调用来运行消息循环GetMessage()TranslateMesage()DispatchMessage()在循环中。无论如何,不​​会直接从第二个线程调用对象方法 - 它们将通过代理。请参阅这篇非常好的文章以获得详尽的解释。

于 2011-06-06T14:46:39.827 回答