我的工作环境是 Erlang。具有 2 个不同功能的进程能否在不同功能中有两个接收块。
receive
....
end.
request()
PID!(message)
%% Can i get the reply back here instead of the receive block above?
是的,你可以有很多receive
表达方式。当一个被评估时,它将从消息队列/邮箱中取出第一条匹配的消息(选择你的名字)并将其余的留给下一个receive
。使用Pid ! Message
语法(唯一的方式)发送消息是完全异步的,只是将消息添加到接收进程消息队列的末尾。receive
是接收消息的唯一方法,即将它们从消息队列中取出。你永远不能把它们放回去。
Erlang 没有内置的同步消息传递,它是一个通过发送两个消息:
“请求”进程向接收进程发送消息,然后进入 areceive
等待回复。
“接收”进程自己会在 a 中获取消息,receive
对其进行处理,将回复消息发送回“请求”进程,然后进入 areceive
等待下一条消息。
请记住,进程之间永远没有内在联系,所有通信都是使用异步消息发送和receive
.
因此,在回答您的第二个问题时:您只能在表达式中得到回复receive
。这是唯一的办法!
抱歉有点迂腐,但 Erlang 没有块或语句。它是一种函数式语言,只有表达式总是返回一个值,即使返回值有时被忽略。
当然,你可以。
接收使用发送运算符 (!) 发送到进程的消息。模式 Pattern 按时间顺序与邮箱中的第一条消息顺序匹配,然后是第二条,依此类推。如果匹配成功并且可选的保护序列 GuardSeq 为真,则评估相应的 Body。匹配的消息被消费,即从邮箱中删除,而邮箱中的任何其他消息保持不变。
以下代码来自supervisor2.erl
项目rabbitmq
。它甚至使用嵌套receive
语句。我在receive
下面标记了嵌套。
terminate_simple_children(Child, Dynamics, SupName) ->
Pids = dict:fold(fun (Pid, _Args, Pids) ->
erlang:monitor(process, Pid),
unlink(Pid),
exit(Pid, child_exit_reason(Child)),
[Pid | Pids]
end, [], Dynamics),
TimeoutMsg = {timeout, make_ref()},
TRef = timeout_start(Child, TimeoutMsg),
{Replies, Timedout} =
lists:foldl(
fun (_Pid, {Replies, Timedout}) ->
{Reply, Timedout1} =
receive %% attention here
TimeoutMsg ->
Remaining = Pids -- [P || {P, _} <- Replies],
[exit(P, kill) || P <- Remaining],
receive {'DOWN', _MRef, process, Pid, Reason} -> %%attention here
{{error, Reason}, true}
end;
{'DOWN', _MRef, process, Pid, Reason} ->
{child_res(Child, Reason, Timedout), Timedout};
{'EXIT', Pid, Reason} ->
receive {'DOWN', _MRef, process, Pid, _} ->
{{error, Reason}, Timedout}
end
end,
{[{Pid, Reply} | Replies], Timedout1}
end, {[], false}, Pids),
timeout_stop(Child, TRef, TimeoutMsg, Timedout),
ReportError = shutdown_error_reporter(SupName),
[case Reply of
{_Pid, ok} -> ok;
{Pid, {error, R}} -> ReportError(R, Child#child{pid = Pid})
end || Reply <- Replies],
ok.