INF: Asynchronous Operations in OLE Applications

ID Number: Q84982

3.10

WINDOWS

Summary:

Under object linking and embedding (OLE) version 1.0, the OLE client

and OLE server libraries communicate using dynamic data exchange (DDE)

messages. Although this behavior will probably change in the future,

the current behavior impacts the application. This article describes

the effects of the asynchronous DDE protocol on an OLE application.

More Information:

Many OLE function calls, in both the OLE client and OLE server

libraries, return the value OLE_WAIT_FOR_RELEASE to signal that the

function initiated an asynchronous operation on a specific object,

document, or server. While an asynchronous operation is in process, an

application must not call any other OLE functions that affect the same

item because only one asynchronous operation per item is supported.

Therefore, when making a sequence of calls that relate to a single

item, the application must wait for each operation to complete before

calling the next.

Synchronizing calls in this manner is called "waiting for release" on

the item in question. While it waits, an application must continue to

process and dispatch messages to exchange DDE messages between the OLE

client and OLE server libraries. The application must enter a special

message loop to perform this processing and to repeatedly check a flag

that indicates that the asynchronous operation is complete.

An OLE server application must determine when the Release method in

OLEOBJECTVTBL, OLESERVERVTBL, or OLESERVERDOCVTBL is called. When an

OLE function returns OLE_WAIT_FOR_RELEASE for an operation on one of

the three items, the server must enter a message loop and check a flag

for each message it processes. For example, the application initially

sets the flag to FALSE and when the server calls a Release method, the

application resets the flag to TRUE. Once the flag is TRUE, the

application exits its message loop because the operation is complete.

This loop is the extent of waiting in an OLE server application.

An OLE client can determine when an OLEOBJECT is released by watching

for an OLE_RELEASE notification in the CallBack method. When the

application receives this notification, it sets a flag that causes the

message loop to exit. An OLEOBJECT is the only item in a client

application that can be busy.

Waiting for All Objects in an OLE Client Application

----------------------------------------------------

Some operations, such as closing a file, in an OLE client application

affect all objects in a document at the same time; waiting for each

object individually is slow. Instead of waiting for each object in

turn, an application can wait for all objects together. Note, however,

that when this technique is used it is more difficult for the

application to articulate errors for individual objects once the

application leaves its message loop. However, for operations such as

document close, the individual errors may not make any difference to

the application.

To wait for all objects at once, maintain a special counter to count

how many objects are released and how many objects are waiting. The

counter is affected by the following four sets of events:

- Before executing any operation on all objects, reset the counter to

zero.

- Increment the counter for each OLE call that returns the

OLE_WAIT_FOR_RELEASE value.

- Decrement the counter for each OLE_RELEASE notification received in

the CallBack method.

- Process and dispatch messages until the counter falls to zero, then

terminate the loop.

While an application that waits for all objects at once is somewhat

more asynchronous during OLE operations, it can be more difficult to

detect and to recover from specific errors. An application that waits

for each object individually as soon as any call returns

OLE_WAIT_FOR_RELEASE uses OLE as a more synchronous protocol. Waiting

for all objects together is an option available to the application

that may be advantageous. The application must take precautions to

ensure that other OLE operations do not occur between time that the

application increments the counter and the time the application waits.

If the application does not take precautions, the counter may fall

below zero.

The OLE_BUSY Return Code

------------------------

If the OLE server related to an object is involved in a modal

operation or an incomplete asynchronous operation, an OLE function

call will return the value OLE_BUSY to indicate that the operation

cannot be executed. The application can either wait for the object to

be released or terminate the operation. Whenever a function returns an

OLE_BUSY value, the OLE client application's CallBack method receives

an OLE_QUERY_RETRY_BUSY notification. The value returned from CallBack

indicates whether or not to continue the operation in response to the

notification. When the application receives this notification, it may

be wise to inform the user and to provide an option to wait or to

cancel.

Debugging Asynchronous Operations

---------------------------------

The process of debugging an application that performs multiple

operations on multiple objects can be quite involved. One method to

address this complexity is to write the application in two phases. In

the first phase of development, the application blocks operations on

all OLE objects when any OLE function returns OLE_WAIT_FOR_RELEASE.

Although waiting for each object in turn will probably cause the

application to run more slowly, the application is much easier to

debug. Waiting for each object effectively converts OLE into a

synchronous protocol.

Once the application has been debugged successfully at phase one, in

phase two, extend the program to operate on several objects

asynchronously. Extending the application in this manner will most

likely improve its performance.

Additional reference words: 3.10