服务无法通过从后台线程的 IServiceProvider.QueryService 获取。 如果使用 QueryService 获取在主线程中的服务,然后尝试使用在后台线程上的服务,它还会失败。
获取从后台线程中的服务,在 IVsPackage.SetSite 方法使用 CoMarshalInterThreadInterfaceInStream 封送处理服务提供程序到主线程的流。 然后可以 unmarshal 在后台线程上的服务提供程序以及使用它访问服务。 您一次只能 unmarshal,因此缓存该接口则会返回。
备注
托管代码自动让线程之间的接口,因此,获取服务从后台线程不需要特殊的代码。
示例
下面的代码将在主线程中向服务提供程序并提供 QueryServiceFromBackgroundThread 方法。 unmarshal 服务提供程序获取从后台线程中的服务。
class CMyPackage : public IVsPackage
{
private:
// Used to marshal IServiceProvider between threads
CComPtr< IStream > m_pSPStream;
// IServiceProvider proxy for the background thread
CComPtr< IServiceProvider > m_pBackgroundSP;
public:
HRESULT SetSite( IServiceProvider* pSP )
{
// Marshal the service provider into a stream so that
// the background thread can retrieve it later
CoMarshalInterThreadInterfaceInStream(
IID_IServiceProvider, pSP, &m_pSPStream);
//... do the rest of your initialization
}
// Call this when your background thread needs to call QueryService
// The first time through, it unmarshals the interface stored
HRESULT QueryServiceFromBackgroundThread(
REFGUID rsid, // [in] Service ID
REFIID riid, // [in] Interface ID
// [out] Interface pointer of requested service (NULL on error)
void **ppvObj
{
if( !m_pBackgroundSP )
{
if( !m_pSPStream )
{
return E_UNEXPECTED;
}
HRESULT hr = CoGetInterfaceAndReleaseStream(
m_pSPStream, IID_IServiceProvider,
(void **)&m_pBackgroundSP );
if( FAILED(hr) )
{
return hr;
}
// The CoGetInterfaceAndReleaseStream has already
// destroyed the stream. To avoid double-freeing,
// the smart wrapper needs to be detached.
m_pSPStream.Detach();
}
return m_pBackgroundSP->QueryService( rsid, riid, ppvObj );
}
};