假设我有一个过程p1和p2。当p1结束时,我也希望p2结束(当p1结束时,p2正在等待用户使用io:get_line()
的输入)。我可以通过让函数自己结束(不再执行代码)来成功结束p1,但我怎么想结束使用p1等待输入的p2?
这些是两个过程的代码:
chat1(2,Chat_Node,Name) ->
timer:sleep(100),
Message = io:get_line(io_lib:format("~s: ", [string:strip(Name,right,$\n)])),
case re:replace(Message, "\\s+", "", [global,{return,list}]) == [$b,$y,$e] of
true ->
Chat_Node ! bye;
false ->
Chat_Node ! {Name, Message},
chat1(2, Chat_Node, Name)
end.
chat2(2,Chat_Node,Name) ->
timer:sleep(100),
Message = io:get_line(io_lib:format("~s: ", [string:strip(Name,right,$\n)])),
case re:replace(Message, "\\s+", "", [global,{return,list}]) == [$b,$y,$e] of
true ->
{msg1, Chat_Node} ! bye;
false ->
{msg1, Chat_Node} ! {Name, Message},
chat2(2, Chat_Node, Name)
end.
在收到用户的输入后,消息将被发送到进程msg1和msg2(Chat_Node)。如果消息是“再见”,则具有“再见”的进程将结束。
答案 0 :(得分:2)
流程P1
可以使用以下功能监控流程P2
:MonitorRef = erlang:monitor(process, P2)
这样做,当{'DOWN', MonitorRef, process, P2, Reason}
终止时它将收到消息P2
,然后在完成之前执行相应的操作。
注意:如果P2正常结束(不再需要执行代码),链接将不起作用。如果P2以normal
修改强>
shell中的一个小例子(需要适应模块)
1> F = fun() -> io:format("Hello~n"),timer:sleep(2000) end.
#Fun<erl_eval.20.52032458>
2> G = fun() -> P2 = spawn(F),
2> MonitorRef = erlang:monitor(process,P2),
2> io:format("P1 waiting for P2 end~n"),
2> receive
2> {'DOWN', MonitorRef, process, P2, Reason} -> io:format("P2 finished with reason ~p~n",[Reason])
2> end,
2> io:format("P1 got message from P2~n")
2> end.
#Fun<erl_eval.20.52032458>
3> spawn(G).
P1 waiting for P2 end
Hello
<0.73.0>
P2 finished with reason normal
P1 got message from P2
4>
修改2
在这个新例子中,P2获得一个浮点数并将其传输到P1。如果输入是浮点数,则在将消息{ok,Value}
发送到P1后,P2会以正常的方式退出,而P1又返回值。如果从字符串到float的转换失败,则P2将退出并显示错误消息,该消息由接收块中的第二个子句捕获。 P1召回自己(愚蠢的错误管理,仅用于说明:o)
1> F = fun(From) ->
1> String = io:get_line("enter a float : "),
1> Float = list_to_float(string:strip(String,both,$\n)),
1> From ! {ok,Float}
1> end.
#Fun<erl_eval.20.52032458>
2> G = fun G() ->
2> P1 = self(),
2> P2 = spawn(fun() -> F(P1) end),
2> MonitorRef = erlang:monitor(process,P2),
2> receive
2> {ok,Float} -> Float;
2> {'DOWN', MonitorRef, process, P2, Reason} ->
2> io:format("this is not a float!"),
2> G()
2> end
2> end.
#Fun<erl_eval.20.52032458>
3> G().
enter a float : 5.2
5.2
4> G().
enter a float : hello
this is not a float!
=ERROR REPORT==== 3-Oct-2016::15:57:03 ===
Error in process <0.66.0> with exit value:
{badarg,[{erlang,list_to_float,["hello"],[]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,674}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,438}]},
{erl_eval,exprs,5,[{file,"erl_eval.erl"},{line,122}]}]}
enter a float : 5.2
5.2
5>