2013-11-15 46 views
0

是否有可能阻止同步函数(handle_call)等待不同模块中的异步调用(handle_cast)?erlang混合同步和异步函数

即 如何才能使同步功能等待(即阻止),直到收到来自异步功能的特定“完成”消息? (然后才继续执行) 这两个模块都遵循gen_server和gen_fsm行为。

handle_info可以以某种方式使用吗?

问候 /彼得

回答

5

这样做是为了节省掉参考发件人handle_call,并在以后调用gen_server:reply的方式。也就是说,当你通常写你handle_call功能是这样的:

handle_call(foo, _From, State) -> 
    {reply, {ok, bar}, State}. 

你会做这样的事情:

handle_call(foo, From, State = #state{pending = Pending}) -> 
    NewState = State#state{pending = [From | Pending]}, 
    {noreply, NewState}. 

再后来,也许在handle_info

handle_info({bar_event, Data}, State = #state{pending = [Head | Tail]) -> 
    gen_server:reply(Head, {ok, Data}), 
    NewState = State#state{pending = Tail}, 
    {noreply, NewState}. 

这意味着当进程调用gen_server:call(Pid, foo)时,它将阻塞,直到服务器进程收到{bar_event, Data},此时服务器将把事件中包含的数据返回给调用者。

我试图通过在“堆栈”中存储关于调用者的信息来简化示例,因此在多个并发调用者的情况下,最后的调用者将首先返回,反之亦然。在很多情况下,您需要使用某种类型的键保存来电者信息,以便在获得异步事件时查找。

这也可以在gen_fsm进程中完成;函数调用和返回值是相似的。

+0

谢谢!这正是我需要的。我完全忘了{noreply,...}“回归”。 – peitur

+1

要小心这样做,因为'gen_server:call'具有5秒的内置超时,之后会自动生成一个错误。超时的长度可以用第三个参数设置,无论是millisecs还是'infinity'。 – rvirding

+0

是的,我在之前的应用程序中遇到过这个问题。现在我通常会设置无穷大或者传递一个超时值(用于回调)。这确实使事情有点“凌乱”,尽管:( – peitur