Call Synchronization
COM applications must be able to deal correctly with user input while processing one or more calls from COM or the operating system. COM provides call synchronization for single-threaded apartments only. Multithreaded apartments (containing free-threaded threads) do not receive calls while making calls (on the same thread). Multithreaded apartments cannot make input synchronized calls. Asynchronous calls are converted to synchronous calls in multithreaded apartments. The message filter is not called for any thread in a multithreaded apartment. For more information about threading issues, see Processes, Threads, and Apartments.
COM calls between processes fall into three categories, as follows:
-
Synchronous calls
-
Most of the communication that takes place within COM is synchronous. When making synchronous calls, the caller waits for the reply before continuing and can receive incoming messages while waiting. COM enters a modal loop to wait for the reply, receiving and dispatching other messages in a controlled manner.
-
Asynchronous notifications
-
When sending asynchronous notifications, the caller does not wait for the reply. COM uses PostMessage or high-level events to send asynchronous notifications, depending on the platform. COM defines five asynchronous methods of IAdviseSink:
Note
While COM is processing an asynchronous call, synchronous calls cannot be made. For example, a container application's implementation of OnDataChange cannot contain a call to IPersistStorage::Save. These calls are the only asynchronous calls supported by COM. There is no way to create a custom interface that is asynchronous at this time.
-
Input-synchronized calls
-
When making input-synchronized calls, the object called must complete the call before yielding control. This helps ensure that focus management works correctly and that data entered by the user is processed appropriately. These calls are made by COM through the SendMessage function, without entering a modal loop. While processing an input-synchronized call, the object called must not call any function or method (including synchronous methods) that might yield control. The following methods are input synchronized
- IOleWindow::GetWindow
- IOleInPlaceActiveObject::OnFrameWindowActivate
- IOleInPlaceActiveObject::OnDocWindowActivate
- IOleInPlaceActiveObject::ResizeBorder
- IOleInPlaceUIWindow::GetBorder
- IOleInPlaceUIWindow::RequestBorderSpace
- IOleInPlaceUIWindow::SetBorderSpace
- IOleInPlaceFrame::SetMenu
- IOleInPlaceFrame::SetStatusText
- IOleInPlaceObject::SetObjectRects
To minimize problems that can arise from asynchronous message processing, the majority of COM method calls are synchronous. With synchronous communication, there is no need for special code to dispatch and handle incoming messages. When an application makes a synchronous method call, COM enters a modal wait loop that handles the required replies and dispatches incoming messages to applications capable of processing them.
COM manages method calls by assigning an identifier called a logical thread ID. A new one is assigned when a user selects a menu command or when the application initiates a new COM operation. Subsequent calls that relate to the initial COM call are assigned the same logical thread ID as the initial call.