2016-10-03 2 views
1

Nehmen wir an, ich habe einen Prozess p1 und p2. Wenn p1 endet, möchte ich auch, dass p2 endet (p2 wartet auf eine Eingabe von dem Benutzer unter Verwendung von io:get_line(), wenn p1 endet). Ich kann p1 erfolgreich beenden, indem ich die Funktion einfach selbst beenden lasse (keinen Code mehr, der ausgeführt werden soll), aber wie soll ich p2 beenden, das auf eine Eingabe mit p1 wartet?Wie beende ich einen Prozess in io: get_line?

Dies sind die Codes für die beiden Prozesse:

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. 

Nachdem eine Eingabe von dem Benutzer zu empfangen, wird die Nachricht an die Prozesse MSG1 und msg2 (Chat_Node) gesendet. Wenn die Nachricht "tschüss" ist, wird der Prozess mit "tschüss" beendet.

Antwort

3

der Prozess P1 den Prozess P2 mit der Funktion überwachen können: MonitorRef = erlang:monitor(process, P2)

so tun, wird die Nachricht {'DOWN', MonitorRef, process, P2, Reason} erhalten, wenn P2 beendet wird und dann die entsprechenden Aktionen durchführen vor der Fertigstellung.

Hinweis: Ein Link würde nicht funktionieren, wenn P2 normal endet (kein Code mehr auszuführen). Es könnte funktionieren, wenn P2 mit einem anderen Grunde tritt als normal

bearbeiten

Ein kleines Beispiel in der Schale (in einem Modul anpassen muß)

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> 

Edit 2

In diesem neuen Beispiel erhält P2 einen Float und überträgt es an P1. Wenn die Eingabe ein Float ist, wird P2 mit einem Grund normal beendet, nachdem die Nachricht {ok,Value} an P1 gesendet wurde, die wiederum nur Value zurückgibt. Wenn die Konvertierung von String in Float fehlschlägt, wird P2 mit einer Fehlermeldung beendet, die von der zweiten Klausel im Empfangsblock abgefangen wird. P1 Rückruf selbst (dummes Fehler-Management, nur zur Veranschaulichung: 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

sich p1 Ende sagen und es wird von p2 überwacht mit 'MonitorRef = erlang: Monitor (Prozess, P1)'. Wie kann p2 '{'DOWN', MonitorRef, process, P1, Reason} verwenden, damit p2 sich selbst beenden kann? – wency

+0

Ich habe meine Antwort bearbeitet – Pascal

+0

Vielen Dank, dass ich schon verstanden habe, wie man Monitore verwendet. Problem ist, dass p2 auf eine Eingabe vom Benutzer mit 'io: get_line() 'wartet, wenn p1 beendet wurde. So, jetzt weiß ich nicht, wie man p2 beendet, wenn p1 endet. Danke trotzdem. – wency

Verwandte Themen