2011-05-04 14 views

cevap

54

İki kolay alternatifiniz var, timer:send_interval/2 veya erlang:send_after/3 kullanın. send_interval'un kurulumu daha kolaydır, send_after (Erlang modülünde kullanıldığında), yerleşik bir işlev olduğundan daha güvenilirdir, bkz. Efficiency Guide.

send_after kullanımı da gen_server işleminin aşırı yüklenmemesini sağlar. Eğer send_interval işlevini kullanıyor olsaydınız, işlemin devam edip etmeyeceğine bakmaksızın bir mesaj alırsınız. send_after ile handle_info'daki dönüşten hemen önce çağrılıyorsanız, yalnızca bir öncekini ele aldığınızda yeni bir mesaj planlayabilirsiniz. Daha doğru bir zaman takibi istiyorsanız, send_after'u, zamanla ?INTERVAL (veya hatta 0) 'dan daha düşük bir değere ayarlayabilmek için programlayabilirsiniz.

Ben senin gen_server aşağıdaki satırlar boyunca bir şey tavsiye ederim: o {trigger, Count} falan gibi gerekirse bir devlet ile bir şeyler gönderebilir

-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), 
    ... 

yerine trigger arasında.

+1

:

erlang:start_timer, http://www.erlang.org/doc/man/erlang.html#start_timer-3 ve http://www.erlang.org/doc/man/erlang.html#send_after-3

Örnek kullanım örneğini görmek için erlang:send_after küçücük bir fark var! Tam olarak şu anda yapıyorum. Teşekkürler! –

+0

Bu, en sonunda senkronizasyondan çıkmayacak, çünkü süreölçer her 6000 + eylemin süresi

+0

@PatrickOscity Elbette, olabilir. Gerçekten emin olmak istiyorsanız, planlamak için gelecek bir süreyi ve bunun yerine gönderilecek milisaniye miktarını hesaplayabilirsiniz. –

1

Aslında, aynı şeyi gerçekleştirmek için gen_server içinde yerleşik bir mekanizma var. gen_server'daki init, tuþ_kullanýcý, tuþ_kullanýcý veya handle_info metodlarýnýn cevap tupleýnýn üçüncü unsuru bir tamsayı ise, bu süreden sonra timeout mesajý mesaja gönderilecek ... bu mesaj, handle_info kullanılarak ele alýnmalýdýr. . eg için:

 
init(Args) -> 
    ... % Start first timer 
    {ok, SomeState, 20000}. %% 20000 is the timeout interval 

handle_call(Input, From, State) -> 
    ... % Do something 
    ... % Do something else 
    {reply, SomeState, 20000}. %% 20000 is the timeout interval 

handle_cast(Input, State) -> 
    ... % Do something 
    ... % Do something else 
    {noreply, SomeState, 20000}. %% 20000 is the timeout interval 


%% A timeout message is sent to the gen_server to be handled in handle_info %% 
handle_info(timeout, State) -> 
    ... % Do the action 
    ... % Start new timer 
    {noreply, SomeState, 20000}. %% "timeout" can be sent again after 20000 ms 

+0

herhangi bir sebeple neden 1 oy verildi? –

+0

Bu doğru. Bu, zaman aşımını manipüle etmeniz gerektiği anlamına gelse de, bu kötü bir fikir olmayabilir. –

+10

'timeout' periyodik yürütme için tasarlanmamıştır. Bu dönemde hiçbir şey olmadığında bir eylem başlatmak veya sona erdirmek amaçlanmıştır. Bu zaman aşımı, bazı sistem ('sys',' proc_lib', ...) eylemleri tarafından bile her eylem tarafından sonlandırılır. Kısaca, zaman aşımı kullanmak, otomatik sonlandırma veya temizleme gibi bazı "bakım" maddeleri dışında güvenmek için cesaret kırılmaz. –

3

kesin zamanlayıcıyı kontrol etmek için erlang:start_timer kullanın ve oluşturduğunuz her zamanlayıcı referansı kaydetmek isteyebilirsiniz. harika

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, 
    ... 
İlgili konular