Win32 RPC 编程(三) 示例下载
我们在上一节的基础上,讨论如何实现异步的 RPC 调用。前两节演示的函数调用都是同步的,即调用函数 Hello() 时,客户端将阻塞住直到服务端的 Hello() 函数返回。如果服务端函数需要进行一些费时的操作,例如复杂的计算、查询,客户端只能一直阻塞在那里。这种情况下,我们可以使用异步的 RPC 提高客户端的性能。
异步的RPC是通过配置文件(.acf)来启用的:
原来的接口 HelloWorld 有两个方法,Hello() 和 Shutdown(),Shutdown() 我们仍然让它是同步调用,所以在.acf文件中不用列出。IDL 接口文件还是可以不用修改。
服务端的代码 server.c 中的 Hello() 要改成下面的样子:
Cpp代码
- void Hello(PRPC_ASYNC_STATE rpcAsyncHandle, const unsigned char * psz)
- {
- // 模拟一个长时间的操作
- printf("Sleep 5 seconds...\n");
- Sleep(5000);
- printf("%s\n", psz);
- // 表明调用已经完成
- RpcAsyncCompleteCall(rpcAsyncHandle, NULL);
- }
服务端的其它代码不用修改。
客户端client.c中的调用方式也要换:
Cpp代码
- int main(int argc, char * argv[])
- {
- // 前面都相同
- ...
- // 下面是调用服务端的函数
- RpcTryExcept
- {
- if ( _stricmp(argv[1], "SHUTDOWN") == 0 )
- {
- Shutdown();
- }
- else
- {
- // 初始化异步调用
- RPC_ASYNC_STATE async;
- RpcAsyncInitializeHandle( &async, sizeof(async) );
- async.UserInfo = NULL;
- async.NotificationType = RpcNotificationTypeNone;
- // 本函数能立即返回
- Hello( &async, (unsigned char*)argv[1]);
- // 查询调用的状态
- while ( RpcAsyncGetCallStatus(&async) == RPC_S_ASYNC_CALL_PENDING )
- {
- printf("Call Hello() pending, wait 1s...\n");
- Sleep(1000);
- }
- // 通知调用已经完成
- RpcAsyncCompleteCall( &async, NULL );
- }
- }
- RpcExcept(1)
- {
- printf( "RPC Exception %d\n", RpcExceptionCode() );
- }
- RpcEndExcept
- // 后面都相同
- ...
- }
- Hello.acf:
- [
- implicit_handle(handle_t HelloWorld_Binding)
- ]
- interface HelloWorld
- {
- [async] Hello(); // 增加了 [async] 表明这是异步调用
- }