首先非常感谢下面几篇文章:
http://groups.yahoo.com/neo/groups/wtl/conversations/topics/16493
http://lang.9sssd.com/awtl/art/480
http://www.codewiz51.com/wiki/ATL-Threading-passing-a-SAFEARRAY-when-raising-an-event.ashx(包含例子下载地址:)
准备工作:
首先你得为你的组件添加了连接点事件。需要修改的文件包括:
(1) TaskManagerCOM_ATL.idl:
添加如下代码:
importlib("stdole2.tlb");
[
uuid(BABA3626-072D-4411-B054-4661EB09847B),
helpstring("_ITaskManagerEvents Interface")
]
dispinterface _ITaskManagerEvents
{
properties:
methods:
[id(1),helpstring("method sendMessage_to_Client")] HRESULT sendMessage_to_Client(
[in] int message_id,
[in] BSTR file_name,
[in] int m_process);
};
(2)在类视图中,编译你的 _ITaskManagerEvents ,添加模板库。
这里应该为 "_ITaskManagerEvents"
(4)步骤4,这是你会发现你的 头文件中多了一个 _ITaskManagerEvents_CP.h,同时在你的组件类上添加了
public CProxy_ITaskManagerEvents<CTaskManager>,
public IConnectionPointContainerImpl<CTaskManager>,
及
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)等代码。
前面的这几个步骤就是向导给我目前提供的代码,在实现完前面的步骤后,你会发现你的COM组件的主线程调用,已经可以调用_ITaskManagerEvents_CP.h中的Fire_sendMessage_to_Client(你的函数可能有所不同)函数了。 当前面的步骤没有什么问题后,接下来就是修改几个点以是它能在多线程环境里面运行的步骤。
下面是实现的步骤:
(1)将ATLCPImplMT.h复制到你的项目文件当中。
(2)修改 _ITaskManagerEvents_CP.h中的
template<class T>
class CProxy_IXXXEvents :
public IConnectionPointImpl<T, &__uuidof(_IXXXEvents)>
为
class CProxy_ITaskManagerEvents :public IConnectionPointImplMT<T, &__uuidof(_ITaskManagerEvents)>template<class T>
修改:
pThis->Lock();
CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
pThis->Unlock();
IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
CComPtr<IUnknown> punkConnection;
punkConnection.Attach (GetInterfaceAt(iConnection));
CComQIPtr<IDispatch> pConnection(punkConnection);
(3)在你的调用线程中,记着要在线程开始和结束时初始化和卸载com库,调用CoInitializeEx(NULL, COINIT_MULTITHREADED);和CoUninitialize();函数;现在可以在其他线程中调用触发函数Fire_XXX函数了!