複数のコールバックのサポート
複数の非同期メソッドを呼び出す場合、それぞれが 個別に IMFAsyncCallback::Invoke を実装する必要があります。 ただし、1 つの C++ クラス内にコールバックを実装することもできます。 クラスには 1 つの Invoke メソッドのみを含めることができるので、1 つのソリューションは、コンテナー クラスの別のメソッドに 対する Invoke 呼び出しをデリゲートするヘルパー クラスを提供することです。
次のコードは、 という名前 AsyncCallback
のクラス テンプレートを示しています。この方法を示します。
//////////////////////////////////////////////////////////////////////////
// AsyncCallback [template]
//
// Description:
// Helper class that routes IMFAsyncCallback::Invoke calls to a class
// method on the parent class.
//
// Usage:
// Add this class as a member variable. In the parent class constructor,
// initialize the AsyncCallback class like this:
// m_cb(this, &CYourClass::OnInvoke)
// where
// m_cb = AsyncCallback object
// CYourClass = parent class
// OnInvoke = Method in the parent class to receive Invoke calls.
//
// The parent's OnInvoke method (you can name it anything you like) must
// have a signature that matches the InvokeFn typedef below.
//////////////////////////////////////////////////////////////////////////
// T: Type of the parent object
template<class T>
class AsyncCallback : public IMFAsyncCallback
{
public:
typedef HRESULT (T::*InvokeFn)(IMFAsyncResult *pAsyncResult);
AsyncCallback(T *pParent, InvokeFn fn) : m_pParent(pParent), m_pInvokeFn(fn)
{
}
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
{
static const QITAB qit[] =
{
QITABENT(AsyncCallback, IMFAsyncCallback),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
}
STDMETHODIMP_(ULONG) AddRef() {
// Delegate to parent class.
return m_pParent->AddRef();
}
STDMETHODIMP_(ULONG) Release() {
// Delegate to parent class.
return m_pParent->Release();
}
// IMFAsyncCallback methods
STDMETHODIMP GetParameters(DWORD*, DWORD*)
{
// Implementation of this method is optional.
return E_NOTIMPL;
}
STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult)
{
return (m_pParent->*m_pInvokeFn)(pAsyncResult);
}
T *m_pParent;
InvokeFn m_pInvokeFn;
};
テンプレート パラメーターは、コンテナー クラスの名前です。
AsyncCallback
コンストラクターには、コンテナー クラスへのポインターと、コンテナー クラスのコールバック メソッドのアドレスという 2 つのパラメーターがあります。 コンテナー クラスは、 クラスの複数のインスタンスを AsyncCallback
メンバー変数として持つことができます。1 つは非同期メソッドごとに 1 つです。 コンテナー クラスは、非同期メソッドを呼び出すときに、適切なAsyncCallback
オブジェクトの IMFAsyncCallback インターフェイスを使用します。 オブジェクトの AsyncCallback
Invoke メソッドが呼び出されると、呼び出しはコンテナー クラスの正しいメソッドに委任されます。
また、 オブジェクトは AsyncCallback
AddRef 呼び出しと Release 呼び出しをコンテナー クラスに委任するため、コンテナー クラスはオブジェクトの有効期間を AsyncCallback
管理します。 これにより、コンテナー オブジェクト自体が AsyncCallback
削除されるまで、オブジェクトは削除されません。
次のコードは、このテンプレートの使用方法を示しています。
#pragma warning( push )
#pragma warning( disable : 4355 ) // 'this' used in base member initializer list
class CMyObject : public IUnknown
{
public:
CMyObject() : m_CB(this, &CMyObject::OnInvoke)
{
// Other initialization here.
}
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
private:
AsyncCallback<CMyObject> m_CB;
HRESULT OnInvoke(IMFAsyncResult *pAsyncResult);
};
#pragma warning( pop )
この例では、コンテナー クラスの名前 CMyObject
は です。
m_CBメンバー変数は オブジェクトですAsyncCallback
。 コンストラクターでは CMyObject
、 m_CB メンバー変数は メソッドの CMyObject::OnInvoke
アドレスで初期化されます。
関連トピック