我們在上一節(jié)的基礎上,討論如何實現(xiàn)異步的 RPC 調(diào)用。前兩節(jié)演示的函數(shù)調(diào)用都是同步的,即調(diào)用函數(shù) Hello() 時,
客戶端將阻塞住直到服務端的 Hello() 函數(shù)返回。如果服務端函數(shù)需要進行一些費時的操作,例如復雜的計算、查詢,
客戶端只能一直阻塞在那里。這種情況下,我們可以使用異步的 RPC 提高客戶端的性能。
異步的RPC是通過配置文件(.acf)來啟用的:
--------------------------------------------
Hello.acf:
[
implicit_handle(handle_t HelloWorld_Binding)
]
interface HelloWorld
{
[async] Hello(); // 增加了 [async] 表明這是異步調(diào)用
}
原來的接口 HelloWorld 有兩個方法,Hello() 和 Shutdown(),Shutdown() 我們?nèi)匀蛔屗峭秸{(diào)用,所以在.acf文
件中不用列出。IDL 接口文件還是可以不用修改。
服務端的代碼 server.c 中的 Hello() 要改成下面的樣子:
------------------------------------------------------
void Hello(PRPC_ASYNC_STATE rpcAsyncHandle, const unsigned char * psz)
{
// 模擬一個長時間的操作
printf("Sleep 5 seconds...\n");
Sleep(5000);
printf("%s\n", psz);
// 表明調(diào)用已經(jīng)完成
RpcAsyncCompleteCall(rpcAsyncHandle, NULL);
}
服務端的其它代碼不用修改。
客戶端client.c中的調(diào)用方式也要換:
---------------------------------
int main(int argc, char * argv[])
{
// 前面都相同
...
// 下面是調(diào)用服務端的函數(shù)
RpcTryExcept
{
if ( _stricmp(argv[1], "SHUTDOWN") == 0 )
{
Shutdown();
}
else
{
// 初始化異步調(diào)用
RPC_ASYNC_STATE async;
RpcAsyncInitializeHandle( &async, sizeof(async) );
async.UserInfo = NULL;
async.NotificationType = RpcNotificationTypeNone;
// 本函數(shù)能立即返回
Hello( &async, (unsigned char*)argv[1]);
// 查詢調(diào)用的狀態(tài)
while ( RpcAsyncGetCallStatus(&async) == RPC_S_ASYNC_CALL_PENDING )
{
printf("Call Hello() pending, wait 1s...\n");
Sleep(1000);
}
// 通知調(diào)用已經(jīng)完成
RpcAsyncCompleteCall( &async, NULL );
}
}
RpcExcept(1)
{
printf( "RPC Exception %d\n", RpcExceptionCode() );
}
RpcEndExcept
// 后面都相同
...
}
這樣客戶端就實現(xiàn)了異步調(diào)用!
示例下載