无法在设置线程模式后对其加以更改
错误代码:2147549446(0x80010106)
经分析,是因为调用CoInitialize()不当所致。遂改用
CoInitializeEx(NULL, COINIT_MULTITHREADED);
问题得以解决。
CoInitialize、CoInitializeEx都是windows的API,主要是告诉windows以什么方式为程序创建COM对象,原因是程序调用com库函数(除CoGetMalloc和内存分配函数)之前必须初始化com库。
注:新的应用程序应该调用CoInitializeEx而不是CoInitialize,一般是在 Dll 中使用 COM 才会需要使用的。
-----------------------------
对于每个使用com库的线程,CoInitializeEx 至少必须调用一次,通常也只调用一次。只要传递相同的并发标志参数,同一个线程多次调用CoInitializeEx也是允许的,但是后面的有效调用返回S_FLASE。 要在一个线程上合理关闭com库,每一次成功调用CoInitialize或者CoInitializeEx (包括任何返回S_FALSE的调用),都必须对应调用一次CoUninitialize。
注意:要使用CoInitializeEx必须在代码开始包含#define _WIN32_DCOM预编译命令
一 个线程,除了调用CoGetMalloc函数和其它内存分配(CoTaskMemAlloc, CoTaskMemFree,CoTaskMemReAlloc, and the IMalloc methods on the task allocationsupplied byCoGetMalloc),在调用任何其它com库函数前必须调用CoInitializeEx或者CoInitialize,,否则com库函数会返回CO_E_NOTINITIALIZED。
一旦线程并发模式被设置,就无法再改变。在线程上再次调用CoInitializeEx,传递与之前初始化调用不同的并发机制参数,函数将返回RPC_E_CHANGED_MODE 错误值。
如果并发模式没有设置dwCoInit参数,默认值取COINIT_MULTITHREADED。
在单线程单元创建的对象,只能从他们的单元线程中接收方法调用,因此调用是序列化的,而且只能通过消息队列(当调用win32函数PeekMessage或SendMessage)到达。
在多线程单元创建的com对象,必须能够在任何时候接收来自其它线程的方法调用。在多线程对象编码中,你可能会使用win32同步机制,譬如临界区、信号量、互斥等来实现并发控制,帮助保护对象数据。
当运行在中立线程单元的对象被STA或MTA线程调用时,该线程转为NTA。如果这个线程在后面调用CoInitializeEx,调用失败,返回RPC_E_CHANGED_MODE错误代码。
CoInitializeEx 提供与CoInitialize相同的功能,而且也提供参数显式指定线程的并发模式。CoInitalize当前实现是通过调用CoInitializeEx,并指定并发模式为单线程单元。今天的应用开发应该调用CoinitializeEx,而不是CoInitialize。
因为OLE技术不是线程安全的,函数OleInitialize调用用CoInitializeEx,并传入参数COINIT_APARTMENTTHREADED标志。因此,初始化为多线程对象并发的单元无法使用OleInitialze激活的特性。
因为没有办法控制进程内服务加载与卸载的顺序,因此不要在DllMain函数内调用CoInitialize,CoInitializeEx, 或 CoUninitialize。