如何在io中终止进程:get_line?

时间:2016-10-03 12:10:54

标签: erlang

假设我有一个过程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)。如果消息是“再见”,则具有“再见”的进程将结束。

1 个答案:

答案 0 :(得分:2)

流程P1可以使用以下功能监控流程P2MonitorRef = 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>