进行异步调用

进行同步调用的过程非常简单:客户端在服务器对象上获取接口指针,并通过该指针调用方法。 异步调用涉及调用对象,因此需要执行的步骤多一点。

对于同步接口上的每种方法,相应的异步接口实现两种方法。 这些方法将前缀 Begin_ 和 Finish_ 附加到同步方法的名称。 例如,如果名为 ISimpleStream 的接口具有 Read 方法,AsyncISimpleStream 接口将具有 Begin_Read 和 Finish_Read 方法。 若要开始异步调用,客户端将调用 Begin_ 方法。

开始异步调用

  1. 查询 ICallFactory 接口的服务器对象。 如果 QueryInterface 返回 E_NOINTERFACE,则服务器对象不支持异步调用。

  2. 调用 ICallFactory::CreateCall 以创建对应于所需接口的调用对象,然后释放指向 ICallFactory 的指针。

  3. 如果未从对 CreateCall 的调用请求指向异步接口的指针,请查询异步接口的调用对象。

  4. 调用相应的 Begin_ 方法。

服务器对象现在正在处理异步调用,客户端可以自由执行其他工作,直到需要调用的结果。

调用对象一次只能处理一个异步调用。 如果同一或第二个客户端在挂起的异步调用完成之前调用 Begin_ 方法,Begin_方法将返回 RPC_E_CALL_PENDING。

如果客户端不需要 Begin_ 方法的结果,则可以在此过程结束时释放调用对象。 COM 会检测这种情况并清理调用。 不调用 Finish_ 方法,客户端不会获取任何 out 参数或返回值。

当服务器对象准备好从 Begin_ 方法返回时,它会向调用对象发出完成信号。 客户端准备就绪后会检查是否已向调用对象发出信号。 如果情况属实,客户端可以完成异步调用。

客户端和服务器之间的这一信号和检查通过调用对象上的 ISynchronize 接口完成。 调用对象通常通过聚合系统提供的同步对象来实现此接口。 同步对象通过调用 ISynchronize::Signal 包装事件句柄,服务器在从 Begin_ 方法返回之前向其发出信号。

完成异步调用

  1. 查询 ISynchronize 接口的调用对象。

  2. 调用 ISynchronize::Wait

  3. 如果 Wait 返回 RPC_E_TIMEOUT,则 Begin_ 方法未完成处理。 客户端可以继续执行其他工作,并稍后再次调用 WaitWait 返回 S_OK 之前,无法调用 Finish_ 方法。

    如果 Wait 返回 S_OK,则 Begin_ 方法已返回。 调用适当的 Finish_ 方法。

Finish_ 方法向客户端传递任何 out 参数。 异步方法的行为(包括 Finish_ 方法的返回值)应与相应同步方法的行为完全匹配。

客户端可以在 Finish_ 方法返回后立即释放调用对象,也可以按住指向调用对象的指针进行其他调用。 在任一情况下,客户端都负责在不再需要对象时释放调用对象。

如果在未进行调用时调用 Finish_ 方法,该方法将返回 RPC_E_CALL_COMPLETE。

注意

如果客户端和服务器对象位于同一单元中,则不保证对 ICallFactory::CreateCall 的调用成功。 如果服务器对象不支持对特定接口进行异步调用,则尝试创建调用对象将失败,并且客户端必须使用同步接口。

 

取消异步调用

异步调用期间的客户端安全性

模拟和异步调用