Bagikan melalui


Memanggil Metode Asinkron

Di Media Foundation, banyak operasi dilakukan secara asinkron. Operasi asinkron dapat meningkatkan performa, karena tidak memblokir utas panggilan. Operasi asinkron di Media Foundation didefinisikan oleh sepasang metode dengan konvensi penamaan Begin... dan End..... Bersama-sama, kedua metode ini mendefinisikan operasi baca asinkron pada aliran.

Untuk memulai operasi asinkron, panggil metode Mulai . Metode Begin selalu berisi setidaknya dua parameter:

  • Penunjuk ke antarmuka IMFAsyncCallback . Aplikasi harus mengimplementasikan antarmuka ini.
  • Penunjuk ke objek status opsional.

Antarmuka IMFAsyncCallback memberi tahu aplikasi ketika operasi selesai. Untuk contoh cara mengimplementasikan antarmuka ini, lihat Menerapkan Callback Asinkron. Objek status bersifat opsional. Jika ditentukan, itu harus mengimplementasikan antarmuka IUnknown . Anda dapat menggunakan objek status untuk menyimpan informasi status apa pun yang diperlukan oleh panggilan balik Anda. Jika Anda tidak memerlukan informasi status, Anda dapat mengatur parameter ini ke NULL. Metode Begin mungkin berisi parameter tambahan yang khusus untuk metode tersebut.

Jika metode Begin mengembalikan kode kegagalan, itu berarti operasi telah gagal segera, dan panggilan balik tidak akan dipanggil. Jika metode Mulai berhasil, itu berarti operasi tertunda, dan panggilan balik akan dipanggil ketika operasi selesai.

Misalnya, metode IMFByteStream::BeginRead memulai operasi baca asinkron pada aliran byte:

    BYTE data[DATA_SIZE];
    ULONG cbRead = 0;

    CMyCallback *pCB = new (std::nothrow) CMyCallback(pStream, &hr);

    if (pCB == NULL)
    {
        hr = E_OUTOFMEMORY;
    }

    // Start an asynchronous request to read data.
    if (SUCCEEDED(hr))
    {
        hr = pStream->BeginRead(data, DATA_SIZE, pCB, NULL);
    }

Metode panggilan balik adalah IMFAsyncCallback::Invoke. Ini memiliki parameter tunggal, pAsyncResult, yang merupakan penunjuk ke antarmuka IMFAsyncResult . Untuk menyelesaikan operasi asinkron, panggil metode Akhir yang cocok dengan metode Begin asinkron. Metode Akhir selalu mengambil pointer IMFAsyncResult . Selalu berikan penunjuk yang sama dengan yang Anda terima dalam metode Panggil . Operasi asinkron tidak selesai sampai Anda memanggil metode Akhir . Anda dapat memanggil metode Akhir dari dalam metode Panggil , atau Anda dapat memanggilnya dari utas lain.

Misalnya, untuk menyelesaikan IMFByteStream::BeginRead pada aliran byte, panggil IMFByteStream::EndRead:

    STDMETHODIMP Invoke(IMFAsyncResult* pResult)
    {
        m_hrStatus = m_pStream->EndRead(pResult, &m_cbRead);

        SetEvent(m_hEvent);

        return S_OK;
    }

Nilai yang dikembalikan dari metode Akhir menunjukkan status operasi asinkron. Dalam kebanyakan kasus, aplikasi Anda akan melakukan beberapa pekerjaan setelah operasi asinkron selesai, apakah berhasil diselesaikan atau tidak. Anda memiliki beberapa opsi:

  • Lakukan pekerjaan di dalam metode Panggil . Pendekatan ini dapat diterima selama aplikasi Anda tidak pernah memblokir utas panggilan atau menunggu apa pun di dalam metode Panggil . Jika Anda memblokir utas panggilan, Anda mungkin memblokir alur streaming. Misalnya, Anda mungkin memperbarui beberapa variabel status, tetapi tidak melakukan operasi baca sinkron atau menunggu pada objek mutex.
  • Dalam metode Panggil , atur peristiwa dan segera kembalikan. Utas panggilan aplikasi menunggu peristiwa dan melakukan pekerjaan ketika peristiwa disinyalkan.
  • Dalam metode Panggil , posting pesan jendela privat ke jendela aplikasi Anda dan segera kembali. Aplikasi melakukan pekerjaan pada perulangan pesannya. (Pastikan untuk memposting pesan dengan memanggil PostMessage, bukan SendMessage, karena SendMessage dapat memblokir utas panggilan balik.)

Penting untuk diingat bahwa Panggil dipanggil dari utas lain. Aplikasi Anda bertanggung jawab untuk memastikan bahwa pekerjaan apa pun yang dilakukan di dalam Invoke aman untuk utas.

Secara default, utas yang memanggil Invoke tidak membuat asumsi tentang perilaku objek panggilan balik Anda. Secara opsional, Anda dapat menerapkan metode IMFAsyncCallback::GetParameters untuk mengembalikan informasi tentang implementasi panggilan balik Anda. Jika tidak, metode ini dapat mengembalikan E_NOTIMPL:

    STDMETHODIMP GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
    {
        // Implementation of this method is optional.
        return E_NOTIMPL;
    }

Jika Anda menentukan objek status dalam metode Mulai , Anda dapat mengambilnya dari dalam metode panggilan balik Anda dengan memanggil IMFAsyncResult::GetState.

Metode Panggilan Balik Asinkron