非同期メソッドの呼び出し
Media Foundation では、多くの操作が非同期的に実行されます。 非同期操作は、呼び出し元のスレッドをブロックしないため、パフォーマンスを向上させることができます。 Media Foundation の非同期操作は、名前付け規則 Begin. と End. を持つメソッドのペアによって定義されます。 これら 2 つのメソッドを組み合わせて、ストリームに対する非同期読み取り操作を定義します。
非同期操作を開始するには、 Begin メソッドを呼び出します。 Begin メソッドには、常に少なくとも 2 つのパラメーターが含まれます。
- IMFAsyncCallback インターフェイスへのポインター。 アプリケーションでは、このインターフェイスを実装する必要があります。
- オプションの状態オブジェクトへのポインター。
IMFAsyncCallback インターフェイスは、操作の完了時にアプリケーションに通知します。 このインターフェイスを実装する方法の例については、「 非同期コールバックの実装」を参照してください。 state オブジェクトは省略可能です。 指定した場合は、 IUnknown インターフェイスを実装する必要があります。 状態オブジェクトを使用して、コールバックで必要な状態情報を格納できます。 状態情報が不要な場合は、このパラメーターを NULL に設定できます。 Begin メソッドには、そのメソッドに固有の追加のパラメーターが含まれている場合があります。
Begin メソッドがエラー コードを返す場合は、操作がすぐに失敗し、コールバックが呼び出されないことを意味します。 Begin メソッドが成功した場合は、操作が保留中であることを意味し、操作の完了時にコールバックが呼び出されます。
たとえば、 IMFByteStream::BeginRead メソッドはバイト ストリームで非同期読み取り操作を開始します。
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);
}
コールバック メソッドは IMFAsyncCallback::Invoke です。 これには、 IMFAsyncResult インターフェイスへのポインターである pAsyncResult という 1 つのパラメーターがあります。 非同期操作を完了するには、非同期 Begin メソッドと一致する End メソッドを呼び出します。 End メソッドは常に IMFAsyncResult ポインターを受け取ります。 Invoke メソッドで受け取ったのと同じポインターを常に渡します。 End メソッドを呼び出すまでは、非同期操作は完了しません。 Invoke メソッド内から End メソッドを呼び出すか、別のスレッドから呼び出すことができます。
たとえば、バイト ストリームで IMFByteStream::BeginRead を完了するには、 IMFByteStream::EndRead を呼び出します。
STDMETHODIMP Invoke(IMFAsyncResult* pResult)
{
m_hrStatus = m_pStream->EndRead(pResult, &m_cbRead);
SetEvent(m_hEvent);
return S_OK;
}
End メソッドの戻り値は、非同期操作の状態を示します。 ほとんどの場合、非同期操作が正常に完了したかどうかに関係なく、アプリケーションは非同期操作の完了後に何らかの作業を実行します。 いくつかのオプションがあります。
- Invoke メソッド内で作業を行います。 この方法は、アプリケーションが呼び出し元のスレッドをブロックしたり 、Invoke メソッド内で何かを待機したりしない限り、許容されます。 呼び出し元のスレッドをブロックすると、ストリーミング パイプラインがブロックされる可能性があります。 たとえば、一部の状態変数を更新しても、同期読み取り操作を実行したり、ミューテックス オブジェクトで待機したりしない場合があります。
- Invoke メソッドで、イベントを設定し、すぐにを返します。 アプリケーションの呼び出し元スレッドはイベントを待機し、イベントが通知されたときに処理を行います。
- Invoke メソッドで、プライベート ウィンドウ メッセージをアプリケーション ウィンドウに投稿し、すぐに返します。 アプリケーションは、そのメッセージ ループで作業を行います。 (SendMessage はコールバック スレッドをブロックできるため、SendMessage ではなく PostMessage を呼び出してメッセージを投稿してください)。
Invoke は別のスレッドから呼び 出 されることを覚えておく必要があります。 アプリケーションは、 Invoke 内で実行されるすべての作業がスレッド セーフであることを確認する責任があります。
既定では、 Invoke を呼び出すスレッドでは、コールバック オブジェクトの動作に関する想定は行われません。 必要に応じて、 IMFAsyncCallback::GetParameters メソッドを実装して、コールバック実装に関する情報を返すことができます。 それ以外の場合、このメソッドは E_NOTIMPLを返すことができます。
STDMETHODIMP GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
{
// Implementation of this method is optional.
return E_NOTIMPL;
}
Begin メソッドで状態オブジェクトを指定した場合は、IMFAsyncResult::GetState を呼び出すことで、コールバック メソッド内から取得できます。
関連トピック