当从.NET COM组件创建MSXML2.DOMDocument()
实例时,它允许中断当前方法执行流并让其他请求在同一个线程上执行,并且当它们完成时,它将恢复初始方法被打断了。
但是在创建MSXML2.FreeThreadedDOMDocument()
实例时没有看到相同的观察结果。在这种情况下,方法执行流程不会中断。
我知道MSXML2.DOMDocument
不是线程安全的,MSXML2.FreeThreadedDOMDocumen
是。但MSXML2.DOMDocument()
的上述行为似乎很奇怪。我错过了什么
您可以使用以下link中的示例应用程序来重现。
MFCApplication - > ATL COM EXE - > .NET COM组件。
- .NET COM组件(dll):
- 开始()=>创建" MSXML2.DOMDocument"文件不确定,直到" _stop"国旗已经设定。
- 停止()=>设置标志" _stop"真实。
- ATL COM EXE:
- CreateCSCOMComponent()=>在COINIT_APARTMENTTHREADED上创建.NET COM组件实例
- Start()=>在.NET COM组件上调用Start()。
停止()=>在.NET COM组件上调用Stop()。
MFCApplication:* Button"启动ATLCOMEXE" :在COINIT_MULTITHREADED中创建一个ATLCOMObject实例的实例,该实例启动 ATLCOMEXE。 * ATLCOMObject-> Start()=>所调用 "&ATLCOMObject- GT;启动()"在一个单独的线程上。 * ATLCOMObject-> Stop()=>调用" ATLCOMObject->停止()"在一个单独的 线程。
重现的步骤:
1)打开MFCApplication。
2)运行debugviewer查看 痕迹
3)点击"启动ATLCOMEXE"
4)点击" ATLCOMObject->开始()"
5)在debugview中连续观察.NET COM对象的日志 创建" MSXML2.DOMDocument()"的实例在同一个thead。
6) 单击" ATLCOMObject->停止()"(一次或多次)。
7)观察 登录debugview,.NET COM对象会中断执行流程 "开始"并执行"停止()"在同一个线程中,"开始"是 执行。
上述行为对我来说似乎很奇怪。
现在,如果我们替换.NET COM组件的Start()
方法中的代码,创建MSXML2.FreeThreadedDOMDocument(
)而不是MSXML2.DOMDocument()
并再次运行上述步骤,我们就不会看到观察7),这至少是我对COM的一点知识所预期的。
所以我想知道在创建MSXML2.DOMDocument
时导致方法执行流中断的原因是什么?
答案 0 :(得分:0)
你的EXE服务器在stdafx.h
中定义了这个(可能是由VS向导添加的):
#define _ATL_APARTMENT_THREADED
CoInitialize(NULL)
初始化COM,这意味着将创建.NET对象的线程将是STA。根据经验,STA线程意味着在此线程中创建的对象的COM消息(=方法调用)由在此线程中运行的COM创建的消息循环泵送。 如果你在该线程中运行自己的循环并且从不让COM消息循环运行,那么任何方法调用都不会到达此STA中的对象。
STA是功能(默认情况下通常默认启用,没有人注意到),这将确保标记为此类的对象不会被随机线程调用并崩溃。
在循环中,当您创建STA实例时,您隐含地让COM循环运行,因此方法调用(Stop)可以完成它。 当您创建FT DomDocument实例时,COM循环根本不运行,并且没有方法调用通过。
您必须了解COM线程如何在您的案例中做出最佳决策。
使用您的示例,您只需更改您的exe代码并发表评论_ATL_APARTMENT_THREADED(the default is _ATL_FREE_THREADED) 在这种情况下,一切都将在MTA中运行(好吧,如果你仍然使用非FT DomDocument,它将在STA上运行。)
注意:必须由线程所有者调用CoInitialize(Ex)。一旦被呼叫,再次呼叫它是没用的。你的代码周围有一些无用的CoInitializeEx。