Condividi tramite


Supporto di più callback

Se si chiama più di un metodo asincrono, ognuno richiede un'implementazione separata di FMAsyncCallback::Invoke. Tuttavia, è possibile implementare i callback all'interno di una singola classe C++. La classe può avere un solo metodo Invoke , quindi una soluzione consiste nel fornire una classe helper che delega le chiamate Invoke a un altro metodo in una classe contenitore.

Il codice seguente mostra un modello di classe denominato AsyncCallback, che illustra questo approccio.

//////////////////////////////////////////////////////////////////////////
//  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;
};

Il parametro modello è il nome della classe contenitore. Il AsyncCallback costruttore ha due parametri: un puntatore alla classe contenitore e l'indirizzo di un metodo di callback nella classe contenitore. La classe contenitore può avere più istanze della AsyncCallback classe come variabili membro, una per ogni metodo asincrono. Quando la classe contenitore chiama un metodo asincrono, usa l'interfaccia FMAsyncCallback dell'oggetto appropriato AsyncCallback . Quando viene chiamato il AsyncCallback metodo Invoke dell'oggetto, la chiamata viene delegata al metodo corretto nella classe contenitore.

L'oggetto AsyncCallback delega anche chiamate AddRef e Release alla classe contenitore, quindi la classe contenitore gestisce la durata dell'oggetto AsyncCallback . Ciò garantisce che l'oggetto non venga eliminato finché l'oggetto AsyncCallback contenitore stesso non viene eliminato.

Il codice seguente illustra come usare questo modello:

#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 )

In questo esempio la classe contenitore è denominata CMyObject. La variabile membro m_CB è un AsyncCallback oggetto. CMyObject Nel costruttore la variabile membro m_CB viene inizializzata con l'indirizzo del CMyObject::OnInvoke metodo.

Metodi di callback asincroni