6.3.6 Asynchronous Operations

When a client application calls a function that invokes a server application, actions taken by the client and server can be asynchronous. For example, the actions of updating a document and closing a server are asynchronous. Whenever an asynchronous operation begins, the client library returns OLE_WAIT_FOR_RELEASE. When a client application receives this notification, it must wait for the OLE_RELEASE notification before it quits. If the client cannot take further action until the asynchronous operation finishes, it should enter a message-dispatch loop and wait for OLE_RELEASE. Otherwise, it should allow the main message loop to continue dispatching messages so that processing can continue.

An application can run only one asynchronous operation at a time for an object; each asynchronous operation must end with the OLE_RELEASE notification before the next one begins. The client's callback function must receive OLE_RELEASE for all pending asynchronous operations before calling the OleRevokeClientDoc function.

Some of the object-creation functions return OLE_WAIT_FOR_RELEASE. The client application can continue to work with the document while waiting for OLE_RELEASE, but some functions (for example, OleActivate) cannot be called until the asynchronous operation has been completed.

If an application calls a function for an object before receiving OLE_RELEASE for that object, the function may return OLE_BUSY. The server also returns OLE_BUSY when processing a new request would interfere with the processing of a current request from a client application or user. When a function returns OLE_BUSY, the client application can display a message reporting the busy condition at this point or it can enter a loop to wait for the function to return OLE_OK. (The OLE_QUERY_RETRY notification is also sent to the client's callback function when the server is busy; when the callback function returns FALSE, the transaction with the server is ended.) Note that if the server uses the OleBlockServer function to postpone OLE activities, the OLE_QUERY_RETRY notification is not sent to the client.

The following example shows a message-dispatch loop that allows a client application to transact messages while waiting for the OLE_RELEASE notification:

while ((olestat = OleQueryReleaseStatus(lpObject)) == OLE_BUSY) {
    if (GetMessage(&msg, NULL, NULL, NULL)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
if (olestat == OLE_ERROR_OBJECT) {
    .
    .  /* The lpObject parameter is invalid. */
    .
}
else { /* if olestat == OLE_OK */
    .
    . /* The object is released, or the server has terminated. */
    .
}

A server application could end unexpectedly while a client is waiting for OLE_RELEASE. In this case, the client library recovers properly only if the client uses the OleQueryReleaseStatus function, as shown in the preceding example.

The following table shows which OLE functions can return the OLE_WAIT_FOR_RELEASE or OLE_BUSY value to a client application:

Function OLE_BUSY OLE_WAIT_FOR_RELEASE

OleActivate Yes Yes
OleClose Yes Yes
OleCopyFromLink Yes Yes
OleCreate No Yes
OleCreateFromClip No Yes
OleCreateFromFile No Yes
OleCreateFromTemplate No Yes
OleCreateLinkFromClip No Yes
OleCreateLinkFromFile No Yes
OleDelete Yes Yes
OleExecute Yes Yes
OleLoadFromStream No Yes
OleObjectConvert Yes No
OleReconnect Yes Yes
OleRelease Yes Yes
OleRequestData Yes Yes
OleSetBounds Yes Yes
OleSetColorScheme Yes Yes
OleSetData Yes Yes
OleSetHostNames Yes Yes
OleSetLinkUpdateOptions Yes Yes
OleSetTargetDevice Yes Yes
OleUnlockServer No Yes
OleUpdate Yes Yes