是否有可能阻止同步函数(handle_call)等待不同模块中的异步调用(handle_cast)?erlang混合同步和异步函数
即 如何才能使同步功能等待(即阻止),直到收到来自异步功能的特定“完成”消息? (然后才继续执行) 这两个模块都遵循gen_server和gen_fsm行为。
handle_info可以以某种方式使用吗?
问候 /彼得
是否有可能阻止同步函数(handle_call)等待不同模块中的异步调用(handle_cast)?erlang混合同步和异步函数
即 如何才能使同步功能等待(即阻止),直到收到来自异步功能的特定“完成”消息? (然后才继续执行) 这两个模块都遵循gen_server和gen_fsm行为。
handle_info可以以某种方式使用吗?
问候 /彼得
这样做是为了节省掉参考发件人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进程中完成;函数调用和返回值是相似的。
谢谢!这正是我需要的。我完全忘了{noreply,...}“回归”。 – peitur
要小心这样做,因为'gen_server:call'具有5秒的内置超时,之后会自动生成一个错误。超时的长度可以用第三个参数设置,无论是millisecs还是'infinity'。 – rvirding
是的,我在之前的应用程序中遇到过这个问题。现在我通常会设置无穷大或者传递一个超时值(用于回调)。这确实使事情有点“凌乱”,尽管:( – peitur