Bagikan melalui


Mendukung Beberapa Panggilan Balik

Jika Anda memanggil lebih dari satu metode asinkron, masing-masing memerlukan implementasi terpisah dari IMFAsyncCallback::Invoke. Namun, Anda mungkin ingin menerapkan panggilan balik di dalam satu kelas C++. Kelas hanya dapat memiliki satu metode Panggil , jadi salah satu solusinya adalah menyediakan kelas pembantu yang mendelegasikan Panggil panggilan ke metode lain pada kelas kontainer.

Kode berikut menunjukkan templat kelas bernama AsyncCallback, yang menunjukkan pendekatan ini.

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

Parameter templat adalah nama kelas kontainer. AsyncCallback Konstruktor memiliki dua parameter: penunjuk ke kelas kontainer, dan alamat metode panggilan balik pada kelas kontainer. Kelas kontainer dapat memiliki beberapa instans AsyncCallback kelas sebagai variabel anggota, satu untuk setiap metode asinkron. Ketika kelas kontainer memanggil metode asinkron, kelas kontainer menggunakan antarmuka IMFAsyncCallback dari objek yang sesuai AsyncCallback . AsyncCallback Ketika metode Panggil objek dipanggil, panggilan didelegasikan ke metode yang benar pada kelas kontainer.

Objek juga AsyncCallback mendelegasikan panggilan AddRef dan Release ke kelas kontainer, sehingga kelas kontainer mengelola masa AsyncCallback pakai objek. Ini menjamin bahwa AsyncCallback objek tidak akan dihapus sampai objek kontainer itu sendiri dihapus.

Kode berikut menunjukkan cara menggunakan templat ini:

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

Dalam contoh ini, kelas kontainer diberi nama CMyObject. Variabel anggota m_CB adalah AsyncCallback objek . CMyObject Dalam konstruktor, variabel anggota m_CB diinisialisasi dengan alamat CMyObject::OnInvoke metode .

Metode Panggilan Balik Asinkron