coinitialize失败,返回值是0x80010106 无法在设置线程模式后对其加以更改

来源:清泛编译     2016-09-06 18:46:53    人气:     我有话说( 0 人参与)

清泛网(www.tsingfun.com):无法在设置线程模式后对其加以更改错误代码:2147549446(0x80010106)经分析,是因为调用CoInitialize()不当所致。遂改用CoInitializeEx(NUL...

无法在设置线程模式后对其加以更改

错误代码:2147549446(0x80010106)

经分析,是因为调用CoInitialize()不当所致。遂改用

CoInitializeEx(NULL, COINIT_MULTITHREADED);

问题得以解决。

 

CoInitialize、CoInitializeEx都是windows的API,主要是告诉windows以什么方式为程序创建COM对象,原因是程序调用com库函数(除CoGetMalloc和内存分配函数)之前必须初始化com库。

 

有哪些方式呢?单线程和多线程。
      CoInitialize指明以单线程方式创建。
      CoInitializeEx可以指定COINIT_MULTITHREADED以多线程方式创建。
      创建单线程方式的COM服务器时不用考虑串行化问题,多线程COM服务器就要考虑。
      在使用中,使用CoInitialize创建可使对象直接与线程连接,得到最高的性能。创建多线程对象可以直接接收所有线程的调用,不必像单线程那样需要消息排队,但却需要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。

来源:http://blog.csdn.net/wxtsmart/archive/2010/05/03/5552190.aspx

coinitialize 失败 0x80010106

注:本文为本站或本站会员原创优质内容,版权属于原作者及清泛网所有,
欢迎转载,转载时须注明版权并添加来源链接,谢谢合作! (编辑:admin)