呼び出しの同期
COM アプリケーションは、COM またはオペレーティング システムからの 1 つ以上の呼び出しの処理中に、ユーザー入力を正しく処理できる必要があります。 COM では、シングル スレッド アパートメントに対してのみ呼び出し同期が提供されます。 マルチスレッド アパートメント (フリー スレッド スレッドスレッドを含む) は、(同じスレッドで) 呼び出しを行っている間は呼び出しを受け取りません。 マルチスレッド アパートメントでは、入力同期呼び出しを行うことはできません。 非同期呼び出しは、マルチスレッド アパートメントの同期呼び出しに変換されます。 メッセージ フィルターは、マルチスレッド アパートメント内のどのスレッドにも呼び出されません。 スレッドの問題の詳細については、「プロセス、スレッド、およびアパートメント」を参照してください。
プロセス間の COM 呼び出しは、次の 3 つのカテゴリに分類されます。
-
同期呼び出しの
-
COM 内で行われる通信のほとんどは同期的です。 同期呼び出しを行うとき、呼び出し元は応答を待機してから続行し、待機中に受信メッセージを受信できます。 COM は、制御された方法で他のメッセージを受信してディスパッチする応答を待機するモーダル ループに入ります。
-
非同期通知を する
-
非同期通知を送信する場合、呼び出し元は応答を待機しません。 COM では、プラットフォームに応じて、PostMessage または高度なイベントを使用して非同期通知を送信します。 COM では、IAdviseSinkの 5 つの非同期メソッドが定義されています。
手記
COM が非同期呼び出しを処理している間は、同期呼び出しを行うことはできません。 たとえば、OnDataChange のコンテナー アプリケーションの実装には、IPersistStorage::Saveへの呼び出しを含めることはできません。 これらの呼び出しは、COM でサポートされている唯一の非同期呼び出しです。 現時点では非同期のカスタム インターフェイスを作成する方法はありません。
-
入力同期呼び出し
-
入力同期呼び出しを行うときは、呼び出されたオブジェクトが制御を生成する前に呼び出しを完了する必要があります。 これにより、フォーカス管理が正しく機能し、ユーザーが入力したデータが適切に処理されるようになります。 これらの呼び出しは、モーダル ループを入力せずに、SendMessage 関数を介して COM によって行われます。 入力同期呼び出しの処理中に、呼び出されたオブジェクトは、制御を生成する可能性のある関数またはメソッド (同期メソッドを含む) を呼び出してはなりません。 次のメソッドは、入力が同期されます
- IOleWindow::GetWindow
- IOleInPlaceActiveObject::OnFrameWindowActivate
- IOleInPlaceActiveObject::OnDocWindowActivate
- IOleInPlaceActiveObject::ResizeBorderをする
- IOleInPlaceUIWindow::GetBorder
- IOleInPlaceUIWindow::RequestBorderSpace
- IOleInPlaceUIWindow::SetBorderSpace
- IOleInPlaceFrame::SetMenu
- IOleInPlaceFrame::SetStatusText
- IOleInPlaceObject::SetObjectRects
非同期メッセージ処理によって発生する可能性のある問題を最小限に抑えるために、COM メソッド呼び出しの大半は同期的です。 同期通信では、受信メッセージをディスパッチして処理する特別なコードは必要ありません。 アプリケーションが同期メソッド呼び出しを行うと、COM は、必要な応答を処理し、受信メッセージを処理できるアプリケーションにディスパッチするモーダル待機ループに入ります。
COM は、論理スレッド IDと呼ばれる識別子を割り当てることで、メソッド呼び出しを管理します。 ユーザーがメニュー コマンドを選択したとき、またはアプリケーションが新しい COM 操作を開始すると、新しいコマンドが割り当てられます。 最初の COM 呼び出しに関連する後続の呼び出しには、最初の呼び出しと同じ論理スレッド ID が割り当てられます。