是否可以阻止同步函数(handle_call)等待另一个模块中的异步调用(handle_cast)?
即。 如何才能使同步函数等待(即阻塞),直到收到来自异步函数的特定“完成”消息? (然后才继续执行) 这两个模块都遵循gen_server和gen_fsm行为。
可以以某种方式使用handle_info吗?
此致 /彼得
答案 0 :(得分: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过程中完成;函数调用和返回值类似。