2016-10-03 52 views
1

假設我有一個進程p1和p2。當p1結束時,我也希望p2結束(當p1結束時,p2正在等待來自用戶的使用io:get_line()的輸入)。我可以通過讓函數自行結束(不需要執行更多代碼)來成功結束p1,但是我想如何結束等待使用p1的輸入的p2?如何在io中終止進程:get_line?

這些是兩個過程的代碼:

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)。如果該消息是「再見」,則具有「再見」的過程將結束。

回答

3

P1可以使用功能監視過程P2過程:MonitorRef = erlang:monitor(process, P2)

否則,它會收到消息時{'DOWN', MonitorRef, process, P2, Reason}P2將終止,然後在完成之前執行相應的操作。

注意:如果P2正常結束(無需執行更多代碼),鏈接將不起作用。如果P2與另一個原因,而不是退出它可以工作normal

編輯

在外殼中的小例子(需要一個模塊中,以適應)

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,而P1返回唯一的值後,P2以正常退出。如果從字符串到浮點的轉換失敗,則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> 
+0

假設P1結束,它是由P2使用'MonitorRef =二郎監視:監視(過程中,P1)'。 p2如何使用'{'DOWN',MonitorRef,進程,P1,Reason}'所以p2可以自行終止? – wency

+0

我編輯了我的答案 – Pascal

+0

謝謝我已經瞭解瞭如何使用顯示器。問題是當p1結束時,p2正在等待來自用戶的使用'io:get_line()'的輸入。所以現在,我不知道如何在p1結束時結束p2。不過謝謝。 – wency