之前我们实验的是在多个线程中创建不同的套间,并且在每个线程中都分别创建单独的com对象。这次实验的是在一个线程中创建对象,然后将对象传递到另外一个线程,再进行调用。我们知道com中是不允许直接把接口指针从一个线程从直接传递到另外一个线程的,当需要传递的时候需要先从当前线程对接口对象进行列集,并且在另外一个接受的线程进行散集,使用散集后的接口指针调用对象提供的方法。下面直接看代码:
先实验APARTMENTTHREADED线程套间,com线程模型为apartment:
1
2 UINT __stdcall _ThreadShowMessage( LPVOID pParam)
3 {
4
5 CString str;
6 str.Format(L"线程二 threadid:%d ,msg:%d", GetCurrentThreadId(), GetCurrentThreadId());
7 MessageBox(NULL, str, str, MB_OK);
8
9
10 CoInitializeEx( NULL, COINIT_APARTMENTTHREADED);
11
12 ITestShowMsg* pShowMsg = NULL;
13 HRESULT hr = ::CoGetInterfaceAndReleaseStream((IStream*)pParam, __uuidof(ITestShowMsg), (void**)&pShowMsg);
14 pShowMsg->ShowMsg( _bstr_t(L"My Message"));
15
16 return 0;
17 }
18
19 UINT __stdcall _ThreadShowMessage2( LPVOID pParam)
20 {
21 CoInitializeEx( NULL, COINIT_APARTMENTTHREADED);
22 {
23 CString str;
24 str.Format(L"线程三 threadid:%d ,msg:%d", GetCurrentThreadId(), GetCurrentThreadId());
25 MessageBox( NULL, str, str, MB_OK);
26
27 ITestShowMsgPtr ptrMsg;
28 HRESULT hr = ptrMsg.CreateInstance( __uuidof(TestShowMsg));
29 ptrMsg->ShowMsg( _bstr_t(L"My Message"));
30
31 //列集对象
32 IStream* pStream = NULL;
33 hr = ::CoMarshalInterThreadInterfaceInStream( __uuidof(ITestShowMsg),ptrMsg,&pStream);
34 //传递IStream到其他线程
35 _beginthreadex( NULL, 0, _ThreadShowMessage, pStream, 0, NULL);
36 MessageBox( NULL, L"将代码停在这里", L"将代码停在这里", MB_OK);
37 //相当于建立消息泵,必须的,不可以用Sleep
38 }
39 return 0;
40 }
41
42 BOOL CrunserviceDlg::OnInitDialog()
43 {
44 CDialog::OnInitDialog();
45 // TODO: 在此添加额外的初始化代码
46
47 //CoInitializeEx( NULL, COINIT_APARTMENTTHREADED);
48 CoInitializeEx( NULL, COINIT_APARTMENTTHREADED);
49 {
50 CString str;
51 str.Format(L"线程一 threadid:%d ,msg:%d", GetCurrentThreadId(), GetCurrentThreadId());
52 MessageBox( str, str, MB_OK);
53
54 ITestShowMsgPtr ptrMsg;
55 HRESULT hr = ptrMsg.CreateInstance( __uuidof(TestShowMsg));
56 ptrMsg->ShowMsg( _bstr_t(L"My Message"));
57
58 //列集对象
59 IStream* pStream = NULL;
60 hr = ::CoMarshalInterThreadInterfaceInStream( __uuidof(ITestShowMsg),ptrMsg,&pStream);
61 //传递IStream到其他线程
62 _beginthreadex( NULL, 0, _ThreadShowMessage, pStream, 0, NULL);
63 MessageBox( L"将代码停在这里1");
64 _beginthreadex( NULL, 0, _ThreadShowMessage2, pStream, 0, NULL);
65 MessageBox( L"将代码停在这里2");
66 }
67
68
69 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
70 }
解释:
以上代码主线程ID为1,在主线程调用COM对象方法,COM执行线程为1,然后启动线程2,并列集COM接口指针传递到线程2,线程2ID为2,com接口散集后执行线程为1.
然后主线程再启动线程3线程,线程3ID为3,调用创建新的COM对象并调用,执行线程为3,然后启动线程4,并列集COM接口指针传递到线程4,线程4ID为4,com接口散集后执行线程为3.
情况2
初始化MULTITHREADED线程套间,com线程模型为free:
主线程ID为1,在主线程调用COM对象方法,COM执行线程为1,然后启动线程2,并列集COM接口指针传递到线程2,线程2ID为2,com接口散集后执行线程为2.
然后主线程再启动线程3线程,线程3ID为3,调用创建新的COM对象并调用,执行线程为3,然后启动线程4,并列集COM接口指针传递到线程4,线程4ID为4,com接口散集后执行线程为4.
情况3
初始化APARTMENTTHREADED线程套间,com线程模型为single:
主线程ID为1,在主线程调用COM对象方法,COM执行线程为1,然后启动线程2,并列集COM接口指针传递到线程2,线程2ID为2,com接口散集后执行线程为1.
然后主线程再启动线程3线程,线程3ID为3,调用创建新的COM对象并调用,执行线程为1,然后启动线程4,并列集COM接口指针传递到线程4,线程4ID为4,com接口散集后执行线程为1