Com线程模型测试

http://blog.csdn.net/xbgprogrammer/article/details/7353921


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

  1. #include "stdafx.h"   
  2. #include <iostream>   
  3. #include <Windows.h>   
  4. #include <atlbase.h>   
  5. #include "../MathSvrLib/MathSvrLib.h"   
  6. #include "../MathSvrLib/MathSvrLib_i.c"   
  7. using namespace std;  
  8.   
  9. CComPtr<IMathObj> pMathObj;  
  10. unsigned __stdcall ThreadFun(void *)  
  11. {  
  12.     HRESULT hr;  
  13.     LONG a = 20;  
  14.     LONG b = 34;  
  15.     LONG sum;  
  16.     hr = pMathObj->Add(a,b,&sum);  
  17.     cout<<a<<"+"<<b<<"="<<sum<<endl;  
  18.     return 0;  
  19. }  
  20.   
  21. int _tmain(int argc, _TCHAR* argv[])  
  22. {  
  23.     CoInitializeEx(NULL,COINIT_MULTITHREADED);  
  24.     HRESULT hr;  
  25.     hr = pMathObj.CoCreateInstance(CLSID_MathObj);  
  26.     LONG a = 10;  
  27.     LONG b = 34;  
  28.     LONG sum;  
  29.     hr = pMathObj->Add(a,b,&sum);  
  30.     cout<<a<<"+"<<b<<"="<<sum<<endl;  
  31.     //创建另外线程调用接口原始指针   
  32.     HANDLE hThread = (HANDLE)_beginthreadex(NULL,NULL,ThreadFun,NULL,NULL,NULL);  
  33.     WaitForSingleObject(hThread,INFINITE);  
  34.     pMathObj.Release();  
  35.     CoUninitialize();  
  36.     return 0;  
  37. }  
#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对象,并且在全局接口表对象注册接口,而后在另一线程中通过全局接口表对象调用此对象,工作正常,以下为示例代码

  1. // Client.cpp : 定义控制台应用程序的入口点。   
  2. //   
  3.   
  4. #include "stdafx.h"   
  5. #include <iostream>   
  6. #include <Windows.h>   
  7. #include <atlbase.h>   
  8. #include "../MathSvrLib/MathSvrLib.h"   
  9. #include "../MathSvrLib/MathSvrLib_i.c"   
  10. using namespace std;  
  11.   
  12. CComPtr<IGlobalInterfaceTable> g_pGIT;  
  13. DWORD g_dwCookie;  
  14. CComPtr<IMathObj> pMathObj;  
  15.   
  16. unsigned __stdcall ThreadFun(void *)  
  17. {  
  18.     //这是必须的,否则g_pGIT->GetInterfaceFromGlobal会提示   
  19.     //尚未调用CoInitialize   
  20.     CoInitialize(NULL);   
  21.     HRESULT hr;  
  22.     LONG a = 20;  
  23.     LONG b = 34;  
  24.     LONG sum;  
  25.     CComPtr<IMathObj> pCalPtr;  
  26.   
  27.     //因为g_pGIT->GetInterfaceFromGlobal会向创建此Com的单元套间发送消息,所以要求   
  28.     //创建此Com对象的单元套间有消息处理,若没有,则GetInterfaceFromGlobal阻塞   
  29.     //若Com接口不支持列集散集,则hr = E_UNEXPECTED   
  30.     hr = g_pGIT->GetInterfaceFromGlobal(g_dwCookie,IID_IMathObj,(void**)&pCalPtr);  
  31.     hr = pCalPtr->Add(a,b,&sum);  
  32.   
  33.     cout<<a<<"+"<<b<<"="<<sum<<endl;  
  34.     CoUninitialize();  
  35.     return 0;  
  36. }  
  37.   
  38. int _tmain(int argc, _TCHAR* argv[])  
  39. {  
  40.     CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);  
  41.     HRESULT hr;  
  42.     hr = pMathObj.CoCreateInstance(CLSID_MathObj);  
  43.     // 创建全局接口表对象   
  44.     hr = g_pGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable,NULL,CLSCTX_INPROC_SERVER);  
  45.     // 注册接口   
  46.     hr = g_pGIT->RegisterInterfaceInGlobal(pMathObj,IID_IMathObj,&g_dwCookie);  
  47.   
  48.     LONG a = 10;  
  49.     LONG b = 34;  
  50.     LONG sum;  
  51.     hr = pMathObj->Add(a,b,&sum);  
  52.     cout<<a<<"+"<<b<<"="<<sum<<endl;  
  53.     //创建另外线程调用接口原始指针   
  54.     HANDLE hThread = (HANDLE)_beginthreadex(NULL,NULL,ThreadFun,NULL,NULL,NULL);  
  55.       
  56.     //消息处理   
  57.     MSG msg;  
  58.     while (GetMessage(&msg, NULL, 0, 0))  
  59.     {  
  60.         TranslateMessage(&msg);  
  61.         DispatchMessage(&msg);  
  62.     }  
  63.   
  64.     pMathObj.Release();  
  65.     CoUninitialize();  
  66.     return 0;  
  67. }  
// 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 应用程序调用一个已为另一线程整理的接口。 )。若以下为示例代码

  1. // Client.cpp : 定义控制台应用程序的入口点。   
  2. //   
  3.   
  4. #include "stdafx.h"   
  5. #include <iostream>   
  6. #include <Windows.h>   
  7. #include <atlbase.h>   
  8. #include "../MathSvrLib/MathSvrLib.h"   
  9. #include "../MathSvrLib/MathSvrLib_i.c"   
  10. using namespace std;  
  11.   
  12. CComPtr<IGlobalInterfaceTable> g_pGIT;  
  13. DWORD g_dwCookie;  
  14. CComPtr<IMathObj> pMathObj;  
  15.   
  16. unsigned __stdcall ThreadFun(void *)  
  17. {  
  18.     //这是必须的,否则g_pGIT->GetInterfaceFromGlobal会提示   
  19.     //尚未调用CoInitialize   
  20.     CoInitialize(NULL);   
  21.     HRESULT hr;  
  22.     LONG a = 20;  
  23.     LONG b = 34;  
  24.     LONG sum;  
  25.     CComPtr<IMathObj> pCalPtr;  
  26.   
  27.     //因为g_pGIT->GetInterfaceFromGlobal会向创建此Com的单元套间发送消息,所以要求   
  28.     //创建此Com对象的单元套间有消息处理,若没有,则GetInterfaceFromGlobal阻塞   
  29.     //若Com接口不支持列集散集,则hr = E_UNEXPECTED   
  30.     hr = g_pGIT->GetInterfaceFromGlobal(g_dwCookie,IID_IMathObj,(void**)&pCalPtr);  
  31.   
  32.     //Error:以下语句会返回hr = 0x8001010e 应用程序调用一个已为另一线程整理的接口。    
  33.     //hr = pMathObj->Add(a,b,&sum);   
  34.   
  35.     //正确的方法   
  36.     hr = pCalPtr->Add(a,b,&sum);  
  37.   
  38.     cout<<a<<"+"<<b<<"="<<sum<<endl;  
  39.     CoUninitialize();  
  40.     return 0;  
  41. }  
  42.   
  43. int _tmain(int argc, _TCHAR* argv[])  
  44. {  
  45.     CoInitializeEx(NULL,COINIT_MULTITHREADED);  
  46.     HRESULT hr;  
  47.     hr = pMathObj.CoCreateInstance(CLSID_MathObj);  
  48.     // 创建全局接口表对象   
  49.     hr = g_pGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable,NULL,CLSCTX_INPROC_SERVER);  
  50.     // 注册接口   
  51.     hr = g_pGIT->RegisterInterfaceInGlobal(pMathObj,IID_IMathObj,&g_dwCookie);  
  52.   
  53.     LONG a = 10;  
  54.     LONG b = 34;  
  55.     LONG sum;  
  56.     hr = pMathObj->Add(a,b,&sum);  
  57.     cout<<a<<"+"<<b<<"="<<sum<<endl;  
  58.     //创建另外线程调用接口原始指针   
  59.     HANDLE hThread = (HANDLE)_beginthreadex(NULL,NULL,ThreadFun,NULL,NULL,NULL);  
  60.     WaitForSingleObject(hThread,INFINITE);  
  61.     pMathObj.Release();  
  62.     CoUninitialize();  
  63.     return 0;  
  64. }  
// 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;
}


以上总计可推理至多线程Com对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值