[英]erlang spawn process error?
我正在按照本教程進行操作,並嘗試編譯event.erl並根據
6> c(event).
{ok,event}
7> rr(event, state).
[state]
8> spawn(event, loop, [#state{server=self(), name="test", to_go=5}]).
<0.60.0>
9> flush().
ok
10> flush().
Shell got {done,"test"}
ok
11> Pid = spawn(event, loop, [#state{server=self(), name="test", to_go=500}]).
<0.64.0>
12> ReplyRef = make_ref().
#Ref<0.0.0.210>
13> Pid ! {self(), ReplyRef, cancel}.
{<0.50.0>,#Ref<0.0.0.210>,cancel}
14> flush().
Shell got {#Ref<0.0.0.210>,ok}
ok
但是我似乎無法通過第8步,因為我收到了此錯誤。
7> spawn(event, loop, [#state{server=self(), name="test", to_go=5}]).
=ERROR REPORT==== 14-Feb-2013::11:14:38 ===
Error in process <0.51.0> with exit value: {function_clause,[{event,loop,[{state,<0.32.0>,"test",5}],[{file,"event.erl"},{line,35}]}]}
<0.51.0>
以下是event.erl
-module(event).
-export([start/2, start_link/2, cancel/1]).
-export([init/3, loop/1]).
-record(state, {server,
name="",
to_go=0}).
%%% Public interface
start(EventName, DateTime) ->
spawn(?MODULE, init, [self(), EventName, DateTime]).
start_link(EventName, DateTime) ->
spawn_link(?MODULE, init, [self(), EventName, DateTime]).
cancel(Pid) ->
%% Monitor in case the process is already dead
Ref = erlang:monitor(process, Pid),
Pid ! {self(), Ref, cancel},
receive
{Ref, ok} ->
erlang:demonitor(Ref, [flush]),
ok;
{'DOWN', Ref, process, Pid, _Reason} ->
ok
end.
%%% Event's innards
init(Server, EventName, DateTime) ->
loop(#state{server=Server,
name=EventName,
to_go=time_to_go(DateTime)}).
%% Loop uses a list for times in order to go around the ~49 days limit
%% on timeouts.
loop(S = #state{server=Server, to_go=[T|Next]}) ->
receive
{Server, Ref, cancel} ->
Server ! {Ref, ok}
after T*1000 ->
if Next =:= [] ->
Server ! {done, S#state.name};
Next =/= [] ->
loop(S#state{to_go=Next})
end
end.
%%% private functions
time_to_go(TimeOut={{_,_,_}, {_,_,_}}) ->
Now = calendar:local_time(),
ToGo = calendar:datetime_to_gregorian_seconds(TimeOut) -
calendar:datetime_to_gregorian_seconds(Now),
Secs = if ToGo > 0 -> ToGo;
ToGo =< 0 -> 0
end,
normalize(Secs).
%% Because Erlang is limited to about 49 days (49*24*60*60*1000) in
%% milliseconds, the following function is used
normalize(N) ->
Limit = 49*24*60*60,
[N rem Limit | lists:duplicate(N div Limit, Limit)].
編輯:我試圖通過從此添加一個參數來更改函數循環
loop(S = #state{server=Server, to_go=[T|Next]}) ->
to this
loop(S = #state{server=Server,name=EventName, to_go=[T|Next]}) ->
並且它仍然可以編譯,但是它不起作用,同樣的錯誤...我想也許是元組不匹配。 然后只會演變為參數to_go=[T|Next]}
不正確。
我認為問題在於您的loop / 1子句將#state參數解包,從而使to_go與列表進行模式匹配(即,to_go = [T | Next])。 但是,您傳入了一個5(to_go = 5),它將無法匹配[T | Next]因此,循環/ 1將不匹配,並且您將沒有匹配的函數子句
loop(#state{server=self(), name="test", to_go=5})
該表達式:
8> spawn(event, loop, [#state{server=self(), name="test", to_go=5}]).
適用於較早版本的代碼,因為它是在整個教程中開發的。 如果我正確閱讀,這應該是正確的電話:
19> event:start("Event", 0).
這與Erlang處理事件錯誤中的問題相同。 start/2
, start_link/2
和time_to_go/1
函數需要一個{{Year,Month,Day},{Hour,Minute,Second}}
形式的時間參數,這就是為什么當您用5
調用它們時它們會失敗的原因。 loop/1
函數期望#state{}
的to_go
字段是一個整數列表,它將解釋為秒,並將通過對每個整數進行一次receive...after
來等待總時間。 該服務器的目標是能夠比Erlang在receive...after
直接等待更長的時間。
time_to_go/1
函數正在計算從現在開始到作為參數輸入的日期/時間之間的秒數,然后將其細分為一個秒數列表,其中秒數不大於receive...after
可以處理的最大大小。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.