2009-04-20 82 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

相关问题