在COM中实现异步是非常复杂但又非常有用的。Process如下:
1. 列集要在线程里使用的接口。
2.Create一个线程。
3. 在线程里Release列集。
4. 调用接口的方法。
头文件如下:
class ATL_NO_VTABLE CAsync
{
protected:
CAsync();
virtual ~CAsync();
private:
unsigned int RunThread();
static unsigned int __stdcall ThreadFunction(void *pFun); //线程函数
HANDLE m_hThread;
protected:
STDMETHOD(EnableAsyncFunction)( IUnknown *pUnkSink); //异步的方法,传入需要列集的接口
/////////////////////////////////////////////////////////////////////
IStream *m_pIStream;
};
源文件如下:
STDMETHODIMP CAsync::EnableAsyncFunction( IUnknown *pUnkSink)
{
HRESULT hr = S_OK;
_AsyncNeedMarshal *m_pIHelper=0;
hr = pUnkSink->QueryInterface(IID__NEED, (void**)&m_pIHelper);
if (SUCCEEDED(hr))
{
//列集m_pIHelper
if( FAILED( ::CoMarshalInterThreadInterfaceInStream(IID__AsyncNeedMarshal,m_pIHelper, &m_pIStream)) )
{
return S_FALSE;
}
m_pIHelper->Release();
}
if (SUCCEEDED(hr))
{
DWORD threadID = 0;
//起线程
m_hThread =CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunction, this, 0, &threadID);
if (0 == m_hThread)
{
hr = E_FAIL;
m_hThread = INVALID_HANDLE_VALUE;
}
}
return hr;
}
unsigned int __stdcall CAsync::ThreadFunction(void *pFun)
{
unsigned int result = 0;
if (pFun)
{
::CoInitialize(0);
//线程函数调用RunThread()方法,真正的运行内容在RunThread()内。
CAsyncMessageReceive &me = *(CAsyncMessageReceive*)pFun;
result = me.RunThread();
::CoUninitialize();
}
return result;
}
unsigned int CAsync::RunThread()
{
_AsyncNeedMarshal *m_pIHelper=0;
//反列集,注意抛出异常的原因有:列集的接口没有在注册表里注册。
HRESULT hr = ::CoGetInterfaceAndReleaseStream(m_pIStream, IID__AsyncNeedMarshal, (void**)&m_pIHelper );
//得到接口对象指针,可以调用该对象的方法了。
m_pIHelper ->Function();
if (m_pIHelper!=NULL)
{
m_pIHelper->Release();
m_pIHelper= 0;
}
return 0;
}