Ayrıca, her dakika bir eylem gerçekleştirecek bir gen_server başlatmak istiyorum.Erlang'ın gen_server ile periyodik olarak eylemler nasıl gerçekleştirilir?
Bunu planlamanın en iyi yolu nedir?
Ayrıca, her dakika bir eylem gerçekleştirecek bir gen_server başlatmak istiyorum.Erlang'ın gen_server ile periyodik olarak eylemler nasıl gerçekleştirilir?
Bunu planlamanın en iyi yolu nedir?
İ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.
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
herhangi bir sebeple neden 1 oy verildi? –
Bu doğru. Bu, zaman aşımını manipüle etmeniz gerektiği anlamına gelse de, bu kötü bir fikir olmayabilir. –
'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. –
da kullanılabilir timer
modül vardır.
http://erldocs.com/R14B02/stdlib/timer.html?i=8&search=timer#cancel_timer/1
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,
...
:
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! –Bu, en sonunda senkronizasyondan çıkmayacak, çünkü süreölçer her 6000 + eylemin süresi
@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. –