Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Jeśli wywołasz więcej niż jedną metodę asynchroniczną, każda z nich wymaga oddzielnej implementacji IMFAsyncCallback::Invoke. Można jednak zaimplementować wywołania zwrotne wewnątrz pojedynczej klasy C++. Klasa może mieć tylko jedną metodę Invoke, dlatego jednym z rozwiązań jest udostępnienie klasy pomocniczej, która deleguje Invoke wywołania do innej metody w klasie kontenera.
Poniższy kod przedstawia szablon klasy o nazwie AsyncCallback, który demonstruje to podejście.
//////////////////////////////////////////////////////////////////////////
// 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;
};
Parametr szablonu jest nazwą klasy kontenera. Konstruktor AsyncCallback ma dwa parametry: wskaźnik do klasy kontenera i adres metody wywołania zwrotnego w klasie kontenera. Klasa kontenera może mieć wiele wystąpień klasy AsyncCallback jako zmiennych składowych, po jednym dla każdej metody asynchronicznej. Gdy klasa kontenera wywołuje metodę asynchroniczną, używa interfejsu IMFAsyncCallback odpowiedniego obiektu AsyncCallback. Gdy wywoływana jest metoda Invoke obiektu AsyncCallback, wywołanie jest delegowane do poprawnej metody w klasie kontenera.
Obiekt AsyncCallback deleguje również AddRef i Release wywołania do klasy kontenera, dzięki czemu klasa kontenera zarządza okresem istnienia obiektu AsyncCallback. Gwarantuje to, że obiekt AsyncCallback nie zostanie usunięty do momentu usunięcia samego obiektu kontenera.
Poniższy kod pokazuje, jak używać tego szablonu:
#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 )
W tym przykładzie klasa kontenera nosi nazwę CMyObject. Zmienna składowa m_CB jest obiektem AsyncCallback. W konstruktorze CMyObject zmienna składowa m_CB jest inicjowana przy użyciu adresu metody CMyObject::OnInvoke.
Tematy pokrewne