在 Erlang 中,消息发送者有什么方法可以等待响应,因此只有在处理完消息后才继续执行?
我的意思是这样的:
Actor ! DoSomething
Continue to this next line of code when DoSomething has been processed
我知道可以通过发送发送者的 Pid 来进行回调,但是还有其他方法可以等待吗?
首先要了解的是,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
大致实现了我刚刚展示的内容。不过,它对程序员是隐藏的。
您可以使用接收块:
http://www.erlang.org/doc/reference_manual/expressions.html#id2270724
从文档中读取:
接收永远不会失败。执行被暂停,可能无限期地暂停,直到消息到达匹配其中一个模式并具有真正的保护序列。
换句话说,发送一条消息并等待回复。
如果接收进程是gen_server,则可以使用gen_server:call
. 例如:
gen_server:call(Pid, Message),
% At this point, we know that the other process has answered.
不,只有异步消息传递。
如果您想有点哲学,那么很难自动定义何时处理消息。是在消息到达进程时,已接收但尚未采取行动,还是在接收进程已采取行动时。这类似于当有人“阅读”我的邮件时收到自动通知。是的,他们看过但他们真的读过吗?
只取决于 jldupont 的情况。如果 web 浏览器向 webmachine 请求一些长期运行的 erlang 资源,则无法使用强制转换来满足该请求。