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.