2016-12-29 9 views

cevap

6

. Eğer metodu Stratus3D'un answer numaralı telefonunda kullanırsanız sonunda geride kalacaksınız.

start_link(Period) when Period > 0, is_integer(Period) -> 
    gen_server:start_link({local, ?SERVER}, ?MODULE, Period, []). 

... 

init(Period) -> 
    StartT = erlang:monotonic_time(millisecond), 
    self() ! tick, 
    {ok, {StartT, Period}}. 

... 

handle_info(tick, {StartT, Period} = S) -> 
    Next = Period - (erlang:monotonic_time(millisecond)-StartT) rem Period, 
    _Timer = erlang:send_after(Next, self(), tick), 
    do_task(), 
    {ok, S}. 

Sen kabuğunda test edebilirsiniz:

spawn(fun() -> 
    P = 1000, 
    StartT = erlang:monotonic_time(millisecond), 
    self() ! tick, 
    (fun F() -> 
     receive 
      tick -> 
      Next = P - (erlang:monotonic_time(millisecond)-StartT) rem P, 
      erlang:send_after(Next, self(), tick), 
      io:format("X~n", []), 
      F() 
     end 
     end)() 
    end). 
+0

bu yöntemle güzel bir şey küçük kaçınılmaz hatalar zaman içinde birikir kalmamasıdır. – Pascal

0

Gerçekten olabildiğince kesin olmak istiyorsanız ve görevinizin gerçekleştirilmesini istediğiniz aralıktan daha az zaman alacağından eminseniz, her 10 ms'de bir işlem oluşturmak yerine uzun bir işlem gerçekleştirebilirsiniz. Erlang her 10 ms'de yeni bir süreç açabilir ama aynı süreci tekrar kullanamayacağınız bir sebep olmadıkça, genellikle (her ne kadar çok az olsa da) yükü almaya değmez.

Bir OTP gen_server böyle bir şey yapacağını: gen_server çalıştığı gibi o kadar ebeveyn olacak çökerse (sürece

periodic_task:start_link(). 

: Sonra böyle gen_server başlatmak

-module(periodic_task). 

... module exports 

start_link() -> 
    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). 

... Rest of API and other OTP callbacks 

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

handle_info(check, OldTimer) -> 
    erlang:cancel_timer(OldTimer), 
    Timer = erlang:send_after(10, self(), check), 
    do_task(), % A function that executes your task 
    {noreply, Timer}. 

Bağlantılı olduklarından dolayı işlem) do_task/0 işlevi neredeyse her 10 milisaniyede bir gerçekleştirilecektir. Bunun kusursuz olmayacağını unutmayın. İcra sürelerinde bir sapma olacak. Gerçek aralık, 10 ms + zamanlayıcı mesajını alacak, eski zamanlayıcıyı iptal edecek ve yenisini başlatacaktır.

Her 10 ms'de bir ayrı bir işlem başlatmak isterseniz, do_task/0 bir işleme sahip olabilirsiniz. Bunun ek yükü ekleyeceğini, ancak spawns arasındaki aralığı daha az kesinleştirmeyeceğini unutmayın.

Benim örnekte, bu cevap alındı: Eğer erlang:monotonic_time/0,1 kullanarak gerçek duvar saati zamanında güvenmelisiniz gerçekten güvenilir ve doğru periyodik süreç istiyorsanız What's the best way to do something periodically in Erlang?

İlgili konular