非同期呼び出しを行う
同期呼び出しを行う手順は簡単です。クライアントはサーバー オブジェクト上のインターフェイス ポインターを取得し、そのポインターを通じてメソッドを呼び出します。 非同期呼び出しには呼び出しオブジェクトが関与するため、さらにいくつかの手順が必要になります。
同期インターフェイスの各メソッドに対して、対応する非同期インターフェイスは 2 つのメソッドを実装します。 これらのメソッドは、同期メソッドの名前にプレフィックス Begin_ および Finish_ を付加します。 たとえば、ISimpleStream という名前のインターフェイスに Read メソッドがある場合、AsyncISimpleStream インターフェイスには Begin_Read メソッドと Finish_Read メソッドがあります。 非同期呼び出しを開始するには、クライアントは Begin_ メソッドを呼び出します。
非同期呼び出しを開始するには
サーバー オブジェクトに ICallFactory インターフェイスをクエリします。 QueryInterface が E_NOINTERFACE を返す場合、サーバー オブジェクトは非同期呼び出しをサポートしていません。
ICallFactory::CreateCall を呼び出して、必要なインターフェイスに対応する呼び出しオブジェクトを作成し、ICallFactory へのポインターを解放します。
CreateCall クエリへの呼び出しから非同期インターフェイスへのポインターを要求しなかった場合は、非同期インターフェイスの呼び出しオブジェクトをクエリします。
適切な Begin_ メソッドを呼び出します。
サーバー オブジェクトは現在非同期呼び出しを処理しており、クライアントは呼び出しの結果が必要になるまで自由に他の作業を行うことができます。
呼び出しオブジェクトは一度に 1 つの非同期呼び出しのみを処理できます。 保留中の非同期呼び出しが終了する前に、同じクライアントまたは 2 番目のクライアントが Begin_ メソッドを呼び出した場合、Begin_ メソッドは RPC_E_CALL_PENDING を返します。
クライアントが Begin_ メソッドの結果を必要としない場合は、このプロシージャの最後に呼び出しオブジェクトを解放できます。 COM はこの状態を検出し、通話をクリーンアップします。 Finish_ メソッドは呼び出されず、クライアントは出力パラメータや戻り値を取得しません。
サーバー オブジェクトが Begin_ メソッドから戻る準備ができると、呼び出しオブジェクトに完了したことを通知します。 クライアントの準備が整うと、呼び出しオブジェクトが通知されたかどうかを確認します。 そうであれば、クライアントは非同期呼び出しを完了できます。
クライアントとサーバー間のこのシグナリングとチェックのメカニズムは、呼び出しオブジェクトの ISynchronize インターフェイスです。 通常、呼び出しオブジェクトは、システム提供の同期オブジェクトを集約することによってこのインターフェイスを実装します。 同期オブジェクトはイベント ハンドルをラップします。サーバーは Begin_ メソッドから戻る直前に ISynchronize::Signal を呼び出して通知します。
非同期呼び出しを完了するには
ISynchronize インターフェイスの呼び出しオブジェクトをクエリします。
ISynchronize::Wait を呼び出します。
Wait が RPC_E_TIMEOUT を返す場合、Begin_ メソッドは処理を終了しません。 クライアントは他の作業を続行し、後で再度 Wait を呼び出すことができます。 Wait が S_OK を返すまで、Finish_ メソッドを呼び出すことはできません。
Wait が S_OK を返す場合、Begin_ メソッドが返されます。 適切な Finish_ メソッドを呼び出します。
Finish_ メソッドはクライアントに出力パラメータを渡します。 非同期メソッドの動作 (Finish_ メソッドの戻り値を含む) は、対応する同期メソッドの動作と正確に一致する必要があります。
クライアントは、Finish_ メソッドが返るとすぐに呼び出しオブジェクトを解放することも、追加の呼び出しを行うために呼び出しオブジェクトへのポインターを保持することもできます。 いずれの場合も、オブジェクトが不要になった場合、クライアントは呼び出しオブジェクトを解放する責任があります。
呼び出しが進行中でないときに Finish_ メソッドを呼び出すと、メソッドは RPC_E_CALL_COMPLETE を返します。
Note
クライアント オブジェクトとサーバー オブジェクトが同じアパートメント内にある場合、ICallFactory::CreateCall の呼び出しが成功する保証はありません。 サーバー オブジェクトが特定のインターフェイスでの非同期呼び出しをサポートしていない場合、呼び出しオブジェクトの作成は失敗し、クライアントは同期インターフェイスを使用する必要があります。
関連トピック