【发布时间】:2013-11-29 00:17:47
【问题描述】:
是否可以阻止同步函数(handle_call)等待不同模块中的异步调用(handle_cast)?
即 如何让同步函数等待(即阻塞),直到收到来自异步函数的特定“完成”消息? (然后才继续执行) 两个模块都遵循 gen_server 和 gen_fsm 行为。
handle_info 可以以某种方式使用吗?
问候 /彼得
【问题讨论】:
标签: asynchronous erlang erlang-otp
是否可以阻止同步函数(handle_call)等待不同模块中的异步调用(handle_cast)?
即 如何让同步函数等待(即阻塞),直到收到来自异步函数的特定“完成”消息? (然后才继续执行) 两个模块都遵循 gen_server 和 gen_fsm 行为。
handle_info 可以以某种方式使用吗?
问候 /彼得
【问题讨论】:
标签: asynchronous erlang erlang-otp
这样做的方法是在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 进程中完成;函数调用和返回值类似。
【讨论】:
gen_server:call 有 5 秒的内置超时,之后会自动生成错误。可以使用第三个参数设置超时长度,毫秒或infinity。