2009-04-20 84 views
28

我有一個過程需要每十五秒做一些工作。目前,我正在做這樣的:在Erlang定期做某些事情的最佳方式是什麼?

 
    -behavior(gen_server). 

    interval_milliseconds()-> 15000. 
    init()-> 
     {ok, 
     _State = FascinatingStateData, 
     _TimeoutInterval = interval_milliseconds() 
     }. 

    %% This gets called automatically as a result of our handlers 
    %% including the optional _TimeoutInterval value in the returned 
    %% Result 
    handle_info(timeout, StateData)-> 
     {noreply, 
     _State = do_some_work(StateData), 
      _TimeoutInterval = interval_milliseconds() 
     }. 

這工作,但它是非常脆:如果我想教我的服務器一個新的消息,當我寫任何新的處理函數,我一定要記住包括其返回值中的可選超時間隔。也就是說,說,如果我處理同步調用,我需要做這樣的:

 
    %% Someone wants to know our state; tell them 
    handle_call(query_state_data, _From, StateData)-> 
     {reply, StateData, _NewStateData = whatever(), interval_milliseconds()}; 

代替

 
    %% Someone wants to know our state; tell them 
    handle_call(query_state_data, _From, StateData)-> 
     {reply, StateData, _NewStateData = whatever()}; 

正如你可能已經猜到,我做了很錯的若干倍。這很討厭,因爲一旦代碼處理了query_state_data消息,就不會再產生超時,整個服務器就會停下來。 (我可以通過在機器上獲取一個shell並手動發送「超時」消息來手動「去纖顫」它,但是...... eww。)

現在,我可以嘗試記住總是指定可選的Timeout參數在我的結果值。但是這並沒有規模:有一天我會忘記,並會再次盯着這個bug。所以:什麼是更好的方法?

我不認爲我想寫一個永久運行的實際循環,並且大部分時間都在睡覺;這似乎與OTP的精神相反。

回答

19

最好的辦法是:

init([]) -> 
    Timer = erlang:send_after(1, self(), check), 
    {ok, Timer}. 

handle_info(check, OldTimer) -> 
    erlang:cancel_timer(OldTimer), 
    do_task(), 
    Timer = erlang:send_after(1000, self(), check), 
    {noreply, Timer}. 
7

使用timer模塊:)

+0

這不是最好的解決辦法:http://erlang.org/doc/efficiency_guide/commoncaveats.html#id60206 – mspanc 2017-09-17 11:59:39

35

使用timer:send_interval/2。例如:

-behavior(gen_server). 

interval_milliseconds()-> 15000. 
init()-> 
    timer:send_interval(interval_milliseconds(), interval), 
    {ok, FascinatingStateData}. 

%% this clause will be called every 15 seconds 
handle_info(interval, StateData)-> 
    State2 = do_some_work(StateData) 
    {noreply, State2}. 
+1

/我嫌額頭 謝謝:) – offby1 2009-04-20 21:17:59

+1

除非你需要準確的超時亞毫秒,然後你需要推出你自己的解決方案 – 2009-04-25 22:11:45

相關問題