Making an Asynchronous Call

The procedure for making a synchronous call is straightforward: The client obtains an interface pointer on the server object and calls methods through that pointer. Asynchronous calling involves a call object, so it involves a few more steps.

For each method on a synchronous interface, the corresponding asynchronous interface implements two methods. These methods attach the prefixes Begin_ and Finish_ to the name of the synchronous method. For example, if an interface named ISimpleStream has a Read method, the AsyncISimpleStream interface will have a Begin_Read and a Finish_Read method. To begin an asynchronous call, the client calls the Begin_ method.

To begin an asynchronous call

  1. Query the server object for the ICallFactory interface. If QueryInterface returns E_NOINTERFACE, the server object does not support asynchronous calling.

  2. Call ICallFactory::CreateCall to create a call object corresponding to the interface you want, and then release the pointer to ICallFactory.

  3. If you did not request a pointer to the asynchronous interface from the call to CreateCall, query the call object for the asynchronous interface.

  4. Call the appropriate Begin_ method.

The server object is now processing the asynchronous call, and the client is free to do other work until it needs the results of the call.

A call object can process only one asynchronous call at a time. If the same or a second client calls a Begin_ method before a pending asynchronous call is finished, the Begin_ method will return RPC_E_CALL_PENDING.

If the client does not need the results of the Begin_ method, it can release the call object at the end of this procedure. COM detects this condition and cleans up the call. The Finish_ method is not called, and the client does not get any out parameters or a return value.

When the server object is ready to return from the Begin_ method, it signals the call object that it is done. When the client is ready, it checks to see whether the call object has been signaled. If so, the client can complete the asynchronous call.

The mechanism for this signaling and checking between client and server is the ISynchronize interface on the call object. The call object normally implements this interface by aggregating a system-supplied synchronization object. The synchronization object wraps an event handle, which the server signals just before returning from the Begin_ method by calling ISynchronize::Signal.

To complete an asynchronous call

  1. Query the call object for the ISynchronize interface.

  2. Call ISynchronize::Wait.

  3. If Wait returns RPC_E_TIMEOUT, the Begin_ method is not finished processing. The client can continue with other work and call Wait again later. It cannot call the Finish_ method until Wait returns S_OK.

    If Wait returns S_OK, the Begin_ method has returned. Call the appropriate Finish_ method.

The Finish_ method passes the client any out parameters. The behavior of the asynchronous methods, including the return value of the Finish_ method, should match exactly that of the corresponding synchronous method.

The client can release the call object as soon as the Finish_ method returns, or it can hold a pointer to the call object to make additional calls. In either case, the client is responsible for releasing the call object when the object is no longer needed.

If you call a Finish_ method when no call is in progress, the method will return RPC_E_CALL_COMPLETE.

Note

If the client and server objects are in the same apartment, calls to ICallFactory::CreateCall are not guaranteed to succeed. If the server object does not support asynchronous calling on a particular interface, the attempt to create a call object will fail and the client must use the synchronous interface.

 

Canceling an Asynchronous Call

Client Security During an Asynchronous Call

Impersonation and Asynchronous Calls