0

我的工作环境是 Erlang。具有 2 个不同功能的进程能否在不同功能中有两个接收块。

receive
....
end.

request()
PID!(message)
%% Can i get the reply back here instead of the receive block above?
4

2 回答 2

11

是的,你可以有很多receive表达方式。当一个被评估时,它将从消息队列/邮箱中取出第一条匹配的消息(选择你的名字)并将其余的留给下一个receive。使用Pid ! Message语法(唯一的方式)发送消息是完全异步的,只是将消息添加到接收进程消息队列的末尾。receive接收消息的唯一方法,即将它们从消息队列中取出。你永远不能把它们放回去。

Erlang 没有内置的同步消息传递,它是一个通过发送两个消息:

  • “请求”进程向接收进程发送消息,然后进入 areceive等待回复。

  • “接收”进程自己会在 a 中获取消息,receive对其进行处理,将回复消息发送回“请求”进程,然后进入 areceive等待下一条消息。

请记住,进程之间永远没有内在联系,所有通信都是使用异步消息发送和receive.

因此,在回答您的第二个问题时:您只能在表达式中得到回复receive。这是唯一的办法!

抱歉有点迂腐,但 Erlang 没有块或语句。它是一种函数式语言,只有表达式总是返回一个值,即使返回值有时被忽略。

于 2012-12-02T01:55:22.037 回答
2

当然,你可以。

接收使用发送运算符 (!) 发送到进程的消息。模式 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.
于 2012-12-01T21:19:42.633 回答