• Com组件编程多线程访问(推荐方法3)


    转载 https://blog.csdn.net/xbgprogrammer/article/details/7353921

    1. 创建Com对象MathObj,线程模型为单元,没有注册PS dll(即不支持列集散集)。客户端为控制台程序,有一全局接口指针,在主线程中创建单元套间,并创建Com对象,而后在另一线程中调用此对象,工作正常,以下为示例代码(但必须说明的是,此种调用方法不符合Com规范)

    #include "stdafx.h"
    
    #include <iostream>
    
    #include <Windows.h>
    
    #include <atlbase.h>
    
    #include "../MathSvrLib/MathSvrLib.h"
    
    #include "../MathSvrLib/MathSvrLib_i.c"
    
    using namespace std;
    
     
    
    CComPtr<IMathObj> pMathObj;
    
    unsigned __stdcall ThreadFun(void *)
    
    {
    
    	HRESULT hr;
    
    	LONG a = 20;
    
    	LONG b = 34;
    
    	LONG sum;
    
    	hr = pMathObj->Add(a,b,&sum);
    
    	cout<<a<<"+"<<b<<"="<<sum<<endl;
    
    	return 0;
    
    }
    
     
    
    int _tmain(int argc, _TCHAR* argv[])
    
    {
    
    	CoInitializeEx(NULL,COINIT_MULTITHREADED);
    
    	HRESULT hr;
    
    	hr = pMathObj.CoCreateInstance(CLSID_MathObj);
    
    	LONG a = 10;
    
    	LONG b = 34;
    
    	LONG sum;
    
    	hr = pMathObj->Add(a,b,&sum);
    
    	cout<<a<<"+"<<b<<"="<<sum<<endl;
    
    	//创建另外线程调用接口原始指针
    
    	HANDLE hThread = (HANDLE)_beginthreadex(NULL,NULL,ThreadFun,NULL,NULL,NULL);
    
    	WaitForSingleObject(hThread,INFINITE);
    
    	pMathObj.Release();
    
    	CoUninitialize();
    
    	return 0;
    
    }
    

      2. 创建Com对象MathObj,线程模型为单元,注册PS dll(若不注册PS dll,IGlobalInterfaceTable.GetInterfaceFromGlobal返回E_UNEXPECTED)。客户端为控制台程序,含有消息循环处理(若没有消息循环处理,IGlobalInterfaceTable.GetInterfaceFromGlobal及通过散集指针调用Com方法会阻塞,因为以上调用会向创建此Com对象的线程发送消息),有一接口指针,在主线程中创建单元套间,创建Com对象,并且在全局接口表对象注册接口,而后在另一线程中通过全局接口表对象调用此对象,工作正常,以下为示例代码

    // Client.cpp : 定义控制台应用程序的入口点。
    
    //
    
     
    
    #include "stdafx.h"
    
    #include <iostream>
    
    #include <Windows.h>
    
    #include <atlbase.h>
    
    #include "../MathSvrLib/MathSvrLib.h"
    
    #include "../MathSvrLib/MathSvrLib_i.c"
    
    using namespace std;
    
     
    
    CComPtr<IGlobalInterfaceTable> g_pGIT;
    
    DWORD g_dwCookie;
    
    CComPtr<IMathObj> pMathObj;
    
     
    
    unsigned __stdcall ThreadFun(void *)
    
    {
    
        //这是必须的,否则g_pGIT->GetInterfaceFromGlobal会提示
    
        //尚未调用CoInitialize
    
        CoInitialize(NULL); 
    
        HRESULT hr;
    
        LONG a = 20;
    
        LONG b = 34;
    
        LONG sum;
    
        CComPtr<IMathObj> pCalPtr;
    
     
    
        //因为g_pGIT->GetInterfaceFromGlobal会向创建此Com的单元套间发送消息,所以要求
    
        //创建此Com对象的单元套间有消息处理,若没有,则GetInterfaceFromGlobal阻塞
    
        //若Com接口不支持列集散集,则hr = E_UNEXPECTED
    
        hr = g_pGIT->GetInterfaceFromGlobal(g_dwCookie,IID_IMathObj,(void**)&pCalPtr);
    
        hr = pCalPtr->Add(a,b,&sum);
    
     
    
        cout<<a<<"+"<<b<<"="<<sum<<endl;
    
        CoUninitialize();
    
        return 0;
    
    }
    
     
    
    int _tmain(int argc, _TCHAR* argv[])
    
    {
    
        CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
    
        HRESULT hr;
    
        hr = pMathObj.CoCreateInstance(CLSID_MathObj);
    
        // 创建全局接口表对象
    
        hr = g_pGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable,NULL,CLSCTX_INPROC_SERVER);
    
        // 注册接口
    
        hr = g_pGIT->RegisterInterfaceInGlobal(pMathObj,IID_IMathObj,&g_dwCookie);
    
     
    
        LONG a = 10;
    
        LONG b = 34;
    
        LONG sum;
    
        hr = pMathObj->Add(a,b,&sum);
    
        cout<<a<<"+"<<b<<"="<<sum<<endl;
    
        //创建另外线程调用接口原始指针
    
        HANDLE hThread = (HANDLE)_beginthreadex(NULL,NULL,ThreadFun,NULL,NULL,NULL);
    
        
    
        //消息处理
    
        MSG msg;
    
        while (GetMessage(&msg, NULL, 0, 0))
    
        {
    
            TranslateMessage(&msg);
    
            DispatchMessage(&msg);
    
        }
    
     
    
        pMathObj.Release();
    
        CoUninitialize();
    
        return 0;
    
    }
    
     

    3.  创建Com对象MathObj,线程模型为单元,注册PS dll(因为要跨套间创建Com对象)。客户端为控制台程序,在主线程中创建多线程套间,并创建Com对象(请注意,此时已得到Com对象的代理指针,而非原始指针),发现进程内多了几个线程(可以判断此时Com设施在背后创建了线程支持单元Com对象调用),而调用此对象,工作正常,并可调试发现方法的调用非主线程,而是Com设施创建的一个线程。若要在另外的线程调用此Com对象,还应该通过列集散集创建Com对象时得到的指针去调用,否则方法调用会返回(hr = 0x8001010e
     应用程序调用一个已为另一线程整理的接口。 )。若以下为示例代码

    // Client.cpp : 定义控制台应用程序的入口点。
    
    //
    
     
    
    #include "stdafx.h"
    
    #include <iostream>
    
    #include <Windows.h>
    
    #include <atlbase.h>
    
    #include "../MathSvrLib/MathSvrLib.h"
    
    #include "../MathSvrLib/MathSvrLib_i.c"
    
    using namespace std;
    
     
    
    CComPtr<IGlobalInterfaceTable> g_pGIT;
    
    DWORD g_dwCookie;
    
    CComPtr<IMathObj> pMathObj;
    
     
    
    unsigned __stdcall ThreadFun(void *)
    
    {
    
        //这是必须的,否则g_pGIT->GetInterfaceFromGlobal会提示
    
        //尚未调用CoInitialize
    
        CoInitialize(NULL); 
    
        HRESULT hr;
    
        LONG a = 20;
    
        LONG b = 34;
    
        LONG sum;
    
        CComPtr<IMathObj> pCalPtr;
    
     
    
        //因为g_pGIT->GetInterfaceFromGlobal会向创建此Com的单元套间发送消息,所以要求
    
        //创建此Com对象的单元套间有消息处理,若没有,则GetInterfaceFromGlobal阻塞
    
        //若Com接口不支持列集散集,则hr = E_UNEXPECTED
    
        hr = g_pGIT->GetInterfaceFromGlobal(g_dwCookie,IID_IMathObj,(void**)&pCalPtr);
    
     
    
        //Error:以下语句会返回hr = 0x8001010e 应用程序调用一个已为另一线程整理的接口。 
    
        //hr = pMathObj->Add(a,b,&sum);
    
     
    
        //正确的方法
    
        hr = pCalPtr->Add(a,b,&sum);
    
     
    
        cout<<a<<"+"<<b<<"="<<sum<<endl;
    
        CoUninitialize();
    
        return 0;
    
    }
    
     
    
    int _tmain(int argc, _TCHAR* argv[])
    
    {
    
        CoInitializeEx(NULL,COINIT_MULTITHREADED);
    
        HRESULT hr;
    
        hr = pMathObj.CoCreateInstance(CLSID_MathObj);
    
        // 创建全局接口表对象
    
        hr = g_pGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable,NULL,CLSCTX_INPROC_SERVER);
    
        // 注册接口
    
        hr = g_pGIT->RegisterInterfaceInGlobal(pMathObj,IID_IMathObj,&g_dwCookie);
    
     
    
        LONG a = 10;
    
        LONG b = 34;
    
        LONG sum;
    
        hr = pMathObj->Add(a,b,&sum);
    
        cout<<a<<"+"<<b<<"="<<sum<<endl;
    
        //创建另外线程调用接口原始指针
    
        HANDLE hThread = (HANDLE)_beginthreadex(NULL,NULL,ThreadFun,NULL,NULL,NULL);
    
        WaitForSingleObject(hThread,INFINITE);
    
        pMathObj.Release();
    
        CoUninitialize();
    
        return 0;
    
    }
    
     
  • 相关阅读:
    数组的应用:一。冒泡排序二。折半查找!二维数组的学习。
    break与continue,while 循环和一维数组的学习及作业
    for循环的应用:迭代法和穷举法
    循环
    称体重
    js js弹出框、对话框、提示框、弹窗总结
    windows 服务器开设端口
    SQL Server 数据库分离与附加(图文教程)
    ASP.NET MVC5 PagedList分页示例
    mvc 连接数据库但单复值得问题
  • 原文地址:https://www.cnblogs.com/profession/p/12149396.html
Copyright © 2020-2023  润新知