9

在 Erlang 中,消息发送者有什么方法可以等待响应,因此只有在处理完消息后才继续执行?

我的意思是这样的:

Actor ! DoSomething
Continue to this next line of code when DoSomething has been processed

我知道可以通过发送发送者的 Pid 来进行回调,但是还有其他方法可以等待吗?

4

5 回答 5

22

首先要了解的是,Erlang 是为处理异步消息传递而构建的。因此,同步消息传递的唯一方法是实现类似于确认的东西。

想象两个进程,P1 和 P2。P1 可能会运行以下代码:

%% process P1 takes the Pid of P2 as a parameter
%% and a Message to pass on to P2
p1(P2, Message) ->
    P2 ! {self(), Message},
    receive
        {P2, ok}
    after 5000 -> % this section is optional, times out after 5s
        exit("P2 didn't process this!") % this kills P1
    end.

P2 本身可能只运行以下命令:

p2() ->
    receive
        {From, Message} ->
            io:format("P2 received message ~p~n",[Message]),
            %% processing is done!
            From ! {self(), ok}
    end.

那么你可能会产生 p2 作为一个新进程。这个会坐等任何消息。然后,当您调用 p1 时,它会向 P2 发送一条消息,然后由 P2 处理它(io:format/2)并回复 P1。因为 P1 正在等待回复,所以在该进程中没有运行其他代码。

这是实现阻塞调用的基本且唯一的方法。使用的建议gen_server:call大致实现了我刚刚展示的内容。不过,它对程序员是隐藏的。

于 2010-02-22T19:38:29.417 回答
4

您可以使用接收块:

http://www.erlang.org/doc/reference_manual/expressions.html#id2270724

从文档中读取:

接收永远不会失败。执行被暂停,可能无限期地暂停,直到消息到达匹配其中一个模式并具有真正的保护序列。

换句话说,发送一条消息并等待回复。

于 2010-02-22T18:04:20.903 回答
4

如果接收进程是gen_server,则可以使用gen_server:call. 例如:

gen_server:call(Pid, Message),
% At this point, we know that the other process has answered.
于 2010-02-22T18:10:28.363 回答
2

不,只有异步消息传递。

如果您想有点哲学,那么很难自动定义何时处理消息。是在消息到达进程时,已接收但尚未采取行动,还是在接收进程已采取行动时。这类似于当有人“阅读”我的邮件时收到自动通知。是的,他们看过但他们真的读过吗?

于 2010-02-23T22:01:11.180 回答
-7

只取决于 jldupont 的情况。如果 web 浏览器向 webmachine 请求一些长期运行的 erlang 资源,则无法使用强制转换来满足该请求。

于 2010-02-22T21:34:47.720 回答