37

さらに、毎分1つのアクションを実行するgen_serverを起動したいと思います。

それをスケジュールするための最良の方法は何ですか?

4

4 に答える 4

59

timer:send_interval/2またはを使用する 2 つの簡単な代替手段がありますerlang:send_after/3send_intervalはセットアップが簡単ですが、send_after(Erlang モジュールで使用する場合) は組み込み関数であるため、より信頼性が高くなります。 Efficiency Guideを参照してください。

を使用send_afterすることで、gen_serverプロセスが過負荷にならないようにすることもできます。関数を使用していたsend_interval場合、プロセスが追いつくことができるかどうかに関係なく、メッセージが表示されます。send_after戻る直前に呼び出されると、前のメッセージhandle_infoを処理した後でのみ、新しいメッセージをスケジュールします。より正確な時間追跡が必要な場合でも、時間を動的に設定して、追いつくためsend_afterにそれよりも低い値 (または 0) に設定することができます。?INTERVAL

あなたの次の行に沿って何かをお勧めしますgen_server

-define(INTERVAL, 60000). % One minute

init(Args) ->
   ... % Start first timer
   erlang:send_after(?INTERVAL, self(), trigger),
   ...

handle_info(trigger, State) ->
   ... % Do the action
   ... % Start new timer
   erlang:send_after(?INTERVAL, self(), trigger),
   ...

代わりに、trigger必要に応じて何かを状態で送信することもできます{trigger, Count}

于 2011-05-04T13:22:10.827 に答える
7

タイマーを正確に制御するには、を使用しerlang:start_timerて、作成した各タイマー参照を保存することをお勧めします。

erlang:start_timerとはわずかな違いがあります。http://www.erlang.org/doc/man/erlang.html#start_timer-3およびhttp://www.erlang.org/doc/man/erlang.html#send_after-3erlang:send_afterを参照してください。

ユースケースの例:

init(Args) ->
    ...
    TRef = erlang:start_timer(?INTERVAL, self(), trigger),
    State = #state{tref = TRef},
    ...

handle_info({timeout, _Ref, trigger}, State) ->
    %% With this cancel call we are able to manually send the 'trigger' message 
    %% to re-align the timer, and prevent accidentally setting duplicate timers
    erlang:cancel(State#state.tref),
    ...
    TRef = erlang:start_timer(?INTERVAL, self(), trigger),
    NewState = State#state{tref = TRef},
    ...

handle_cast(stop_timer, State) ->
    TRef = State#state.tref,
    erlang:cancel(TRef),

    %% Remove the timeout message that may have been put in our queue just before 
    %% the call to erlang:cancel, so that no timeout message would ever get 
    %% handled after the 'stop_timer' message
    receive
        {timeout, TRef, _} -> void
        after 0 -> void
    end,
    ...
于 2012-09-13T06:27:13.147 に答える
1

実際には、gen_server 内に同じことを行うための組み込みメカニズムがあります。init、handle_call、handle_cast、または handle_info メソッドの応答タプルの 3 番目の要素がgen_server整数である場合、timeoutメッセージはミリ秒単位でその時間の経過後にプロセスに送信されます...これは、handle_info を使用して処理する必要があります。例:

init(引数) ->
   ... % 最初のタイマーを開始
   {わかりました、SomeState、20000}。%% 20000 はタイムアウト間隔です

handle_call(入力、送信元、状態) ->
   ... % 何かをする
   ... % 他のことをする
   {返信、SomeState、20000}。%% 20000 はタイムアウト間隔です

handle_cast(入力、状態) ->
   ... % 何かをする
   ... % 他のことをする
   {いや、SomeState、20000}。%% 20000 はタイムアウト間隔です


%% タイムアウト メッセージが gen_server に送信され、handle_info で処理されます %%
handle_info(タイムアウト、状態) ->
   ... % アクションを行う
   ... % 新しいタイマーを開始
   {いや、SomeState、20000}。%% "timeout" は 20000 ミリ秒後に再度送信できます

于 2011-05-05T03:30:49.860 に答える
0

timer使用できるモジュールもあります。

http://erldocs.com/R14B02/stdlib/timer.html?i=8&search=timer#cancel_timer/1

于 2011-05-06T06:53:32.370 に答える