2016-12-05 40 views
0

我想在10秒定時器上更新我的進程狀態。如何在計時器上更新我的PID?

-define(INTERVAL, 3000). 

start_link() -> 
    gen_server:start_link(?MODULE, [], []). 

action(Pid, Action) -> 
    gen_server:call(Pid, Action). 

init([]) -> 
    erlang:send_after(?INTERVAL, self(), trigger), 
    {ok, temple:new()}. 

我想要做的就是把這種

handle_call({fight}, _From, Temple) -> 
    NewTemple = temple:fight(Temple), 
    {reply, NewTemple, NewTemple}; 

所以我嘗試

handle_info(trigger, _State) -> 
    land:action(self(), {fight}), 
    erlang:send_after(?INTERVAL, self(), trigger); 

,但我得到

=ERROR REPORT==== 4-Dec-2016::19:00:35 === 
** Generic server <0.400.0> terminating 
** Last message in was trigger 
** When Server state == {{dict,0,16,16,8,80,48, 
           {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[], 
           []}, 
           {{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[], 
           []}}}, 
         []} 
** Reason for termination == 
** {function_clause,[{land,terminate, 
          [{timeout,{gen_server,call,[<0.400.0>,{fight}]}}, 
          {{dict,0,16,16,8,80,48, 
            {[],[],[],[],[],[],[],[],[],[],[],[],[],[], 
            [],[]}, 
            {{[],[],[],[],[],[],[],[],[],[],[],[],[], 
            [],[],[]}}}, 
          []}], 
          [{file,"src/land.erl"},{line,47}]} 

回答

0

錯誤消息意味着沒有terminate條款中的土地服務er模塊,編譯陸地服務器模塊時應該有警告。

terminate子句被調用,因爲在參數(Pid = <0.400.0>, Message = {fight})的gen_server調用期間發生超時,該行在land:action(self(), {fight}),行上被調用。對gen_server的調用必須在最大時間內完成,默認情況下爲5000ms,您必須減少在拼圖操作中花費的時間。

請注意,由於gen_server調用被阻塞,因此增加服務器超時並不是一個好主意:在執行gen_server調用期間,不能處理新消息,並且在您的示例中,它也會阻止代碼handle_info(trigger, _State)

最後一點,條款handle_info(trigger, _State)應該返回一個形式爲{noreply,NewState}的元組,而最後一行erlang:send_after(?INTERVAL, self(), trigger);返回一個定時器引用,您必須修改這一行。

1

看起來您用land:action(self(), {fight}),您正在嘗試製作一個call到您正在處理該消息的同一gen_server。兩個重要的事實將解釋爲什麼這不起作用:

  • A call總是等待結果返回。
  • gen_server是一個進程,一個進程一次只能處理一個消息。

在處理trigger消息,你說要call回自己,等待自己來處理{fight}消息。由於您正在處理消息的中間,所以您將永遠不會收到{fight}消息。你與自己陷入僵局。這就是爲什麼你會得到暫停。

P.S.發佈SSCCE更有可能爲您提供良好的答案。

相關問題