什么是在Erlang定期做某些事情的最佳方法? [英] What's the best way to do something periodically in Erlang?

查看:75
本文介绍了什么是在Erlang定期做某些事情的最佳方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个进程需要每十五秒钟做一些工作。我目前正在这样做:

 
-behavior(gen_server)。

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

%%由于我们的处理程序
%%,因此返回的
%%中的可选_TimeoutInterval值被自动调用
handle_info(timeout,StateData ) - >
{noreply,
_State = do_some_work(StateData),
_TimeoutInterval = interval_milliseconds()
}。

这是非常脆弱的:如果我想教我的服务器一个新的消息,当我写任何新的处理函数时,我必须记住在其返回值中包含可选的超时间隔。也就是说,如果我正在处理同步电话,我需要这样做:

 
%%有人想知道我们的状态;告诉他们
handle_call(query_state_data,_From,StateData) - >
{reply,StateData,_NewStateData = whatever(),interval_milliseconds()};

而不是

 
%%有人想要知道我们的国家;告诉他们
handle_call(query_state_data,_From,StateData) - >
{reply,StateData,_NewStateData = whatever()};

您可能会猜到,我已经犯了很多错误。这是令人讨厌的,因为一旦代码处理了query_state_data消息,超时就不再生成,整个服务器都会停止。 (我可以通过在机器上获取外壳并手动发送超时消息来手动除颤,但是... eww。)



现在,我可以尝试记住总是在我的Result值中指定可选的Timeout参数。但这并不规模:有一天我会忘记,并会再次盯着这个bug。那么,有什么更好的方法?



我不认为我想写一个永远运行的实际循环,并花费大部分时间睡觉;这似乎违背了OTP的精神。

解决方案

最好的方法是:

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

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


I have a process that needs to do some work every fifteen seconds. I'm currently doing it like this:

    -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 ()
        }.

This works, but it's extremely brittle: if I want to teach my server a new message, when I write any new handler function, I have to remember to include the optional timeout interval in its return value. That is, say if I'm handling a synchronous call, I need to do this:

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

instead of

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

As you might guess, I've made that very mistake a number of times. It's nasty, because once the code handles that query_state_data message, the timeouts no longer get generated, and the whole server grinds to a halt. (I can "defibrillate" it manually by getting a shell on the machine and sending a "timeout" message by hand, but ... eww.)

Now, I could try to remember to always specify that optional Timeout parameter in my Result value. But that doesn't scale: I'll forget someday, and will be staring at this bug once again. So: what's a better way?

I don't think I want to write an actual loop that runs forever, and spends most of its time sleeping; that seems counter to the spirit of OTP.

解决方案

The best way is:

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}.

这篇关于什么是在Erlang定期做某些事情的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆