• CoInitialize()、CoInitializeEx()和AfxOleInit()区别联系


    CoInitialize()和AfxOleInit()

    都是初始化COM库,不同之处在与:

    OLE是建立在COM之上的技术,层次比COM要高。AfxOleInit()调用的是OleInitialize(),而 OleInitialize()除了调用CoInitializeEx()来初始化COM库外,还进行一些其它的操作,这些操作对OLE应用来说是必须的,这些OLE应用包括:  
        (1)Clipboard;  
        (2)Drag   and   drop;  
        (3)Object   linking   and   embedding(现在的OLE,已不再仅仅是Object   linking   and   embedding的概念);  
        (4)In-place   activation;  
        与AfxOleInit()对应的是,AfxOleTerm()。  

        AfxOleInit()和AfxOleTerm()其实也是需要成对的,但是,在你的程序中,AfxOleTerm()可以不出现,这是因为,MFC已经帮你做好了(有兴趣的话,你可以仔细研究一下CWinThread::m_lpfnOleTermOrFreeLib,而CWinApp是从CWinThread继承的)。

    注:但是当你的函数出现了重复调用AfxOleInit()时间便不能依靠mfc自动调用了,需要显式的调用AfxOleTerm清理com库

    CoInitialize与AfxOleInit

    使用MFC的控制台主程序中如果用AfxOleInit()初始化com就会出现DLL中调用wordApp.CreateDispatch("Word.Application",NULL)失败,而改用用CoInitialize()则会成功

    在AfxOleInit()函数中设置断点调试之后可以知道:afxContextIsDLL这个标志的值为ture,因而它并不会去调用OleInitialize,进而不会调用CoInitialize.

    MSDN(If AfxOleInit is called from an MFC DLL, the call will fail. The failure occurs because the function assumes that, if it is called from a DLL, the OLE system was previously initialized by the calling application.) 看来在这个函数中把当前项目当做DLL来处理了.^_^,不知是不是MFC本身的bug

     1 BOOL AFXAPI AfxOleInit()
     2 {
     3     _AFX_THREAD_STATE* pState = AfxGetThreadState();
     4     ASSERT(!pState->m_bNeedTerm);    // calling it twice?
     5 
     6     // Special case DLL context to assume that the calling app initializes OLE.
     7     // For DLLs where this is not the case, those DLLs will need to initialize
     8     // OLE for themselves via OleInitialize.  This is done since MFC cannot provide
     9     // automatic uninitialize for DLLs because it is not valid to shutdown OLE
    10     // during a DLL_PROCESS_DETACH.
    11     if (afxContextIsDLL)
    12     {
    13         pState->m_bNeedTerm = -1;  // -1 is a special flag
    14         return TRUE;
    15     }
    16 
    17     // first, initialize OLE
    18     SCODE sc = ::OleInitialize(NULL);
    19     if (FAILED(sc))
    20     {
    21         // warn about non-NULL success codes
    22 #ifdef _DEBUG
    23         TRACE(traceOle, 0, _T("Warning: OleInitialize returned scode = %s.
    "),
    24             AfxGetFullScodeString(sc));
    25 #endif
    26         goto InitFailed;
    27     }
    28     // termination required when OleInitialize does not fail
    29     pState->m_bNeedTerm = TRUE;
    30 
    31     // hook idle time and exit time for required OLE cleanup
    32     CWinThread* pThread; pThread = AfxGetThread();
    33     ASSERT(pThread);
    34     pThread->m_lpfnOleTermOrFreeLib = AfxOleTermOrFreeLib;
    35 
    36     // allocate and initialize default message filter
    37     if (pThread->m_pMessageFilter == NULL)
    38     {
    39         pThread->m_pMessageFilter = new COleMessageFilter;
    40         ASSERT(AfxOleGetMessageFilter() != NULL);
    41         AfxOleGetMessageFilter()->Register();
    42     }
    43     return TRUE;
    44 
    45 InitFailed:
    46     AfxOleTerm();
    47     return FALSE;
    48 }

    COM中CoInitializeEx 与CoInitialize的区别

    CoInitialize、CoInitializeEx都是windows的API,主要是告诉windows以什么方式为程序创建COM对象,原因是程序调用com库函数(除CoGetMalloc和内存分配函数)之前必须初始化com库。
        CoInitialize指明以单线程方式创建。
        CoInitializeEx可以指定COINIT_MULTITHREADED以多线程方式创建。
        创建单线程方式的COM服务器时不用考虑串行化问题,多线程COM服务器就要考虑。

        CoInitialize并不装载com库,这个函数只是用来初始化当前线程使用什么样的套间。当使用这个函数以后,线程就和一个套间建立了对应关系。
        线程的套间模式决定了该线程如何调用com对象,是否需要列集等

        套间是com中用来解决并发调用冲突的很有效的办法
        Before calling any COM functions, a thread needs to call CoInitialize to load the COM infrastructure (and to enter an apartment). Once a thread calls CoInitialize, the thread is free to call COM APIs.

        CoInitializeEx provides the same functionality as CoInitialize and also provides a parameter to explicitly specify the thread's concurrency model. The current implementation of CoInitialize calls CoInitializeEx and specifies the concurrency model as single-thread apartment. Applications developed today should call CoInitializeEx rather than CoInitialize.

        注:新的应用程序应该调用CoInitializeEx而不是CoInitialize,否则就会有必要在之后每个调用Com的线程中调用CoInitialize来初始化出每个线程自己的套间。

  • 相关阅读:
    C# 安装包中添加卸载
    如何提取json里面的数据
    JSON写入
    在Net下处理Json
    Linq To Json
    衡量视频序列特性的TI(时间信息)和SI(空间信息)
    DotCMS安装步骤
    【12c OCP】最新CUUG OCP071考试题库(52题)
    【ocp12c】最新Oracle OCP071考试题库(44题)
    【Oracle 12c】最新CUUG OCP071考试题库(53题)
  • 原文地址:https://www.cnblogs.com/MuyouSome/p/3449597.html
Copyright © 2020-2023  润新知