2013-06-29 16 views
11

Mam na myśli używanie C# async \ czeka na serwer gry MMO z logiką sterowaną zdarzeniami. Załóżmy, że istnieją tysiące podmiotów wykonujących pewne prace o znanym czasie trwania. Więc chciałbym wywołać Time.Delay() dla każdego z moich obiektów gry. (Jest to podejście przeciwne do zwykłej nieskończonej pętli z pewnym wezwaniem Update() dla każdego obiektu gry.)Ile kosztuje korzystanie z Task.Delay()?

Czy ktoś wie, w jaki sposób jest zaimplementowana Task.Delay()? Czy używasz timerów? Czy jest obciążony zasobami systemowymi?

Czy można odradzać tysiące równoczesnych inwokacji Task.Delay()?

+4

@ColeJohnson Ponieważ 'Thread.Sleep' nie jest' async'? –

+0

A Task.Delay to? To nie ma sensu. Jeśli chcę opóźnić wątek, chcę go TERAZ, nie odradzając kolejnego wątku, by powiedzieć, żeby się zatrzymał. –

+0

@Cole Ważne jest, aby wątek poczekał chwilę przed wznowieniem. Chodzi o to, aby nie opóźniać wątku. –

Odpowiedz

17

Task.Delay jest realizowany w następujący sposób:

public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken) 
{ 
    //error checking 
    Task.DelayPromise delayPromise = new Task.DelayPromise(cancellationToken); 
    if (cancellationToken.CanBeCanceled) 
    delayPromise.Registration = cancellationToken.InternalRegisterWithoutEC((Action<object>) (state => ((Task.DelayPromise) state).Complete()), (object) delayPromise); 
    if (millisecondsDelay != -1) 
    { 
    delayPromise.Timer = new Timer((TimerCallback) (state => ((Task.DelayPromise) state).Complete()), (object) delayPromise, millisecondsDelay, -1); 
    delayPromise.Timer.KeepRootedWhileScheduled(); 
    } 
    return (Task) delayPromise; 
} 

pewno używa czasomierze. Są używane w klasie o nazwie DelayPromise. Oto implementacja:

private sealed class DelayPromise : Task<VoidTaskResult> 
{ 
    internal readonly CancellationToken Token; 
    internal CancellationTokenRegistration Registration; 
    internal Timer Timer; 

    internal DelayPromise(CancellationToken token) 
    { 
    this.Token = token; 
    } 

    internal void Complete() 
    { 
    if (!(this.Token.IsCancellationRequested ? this.TrySetCanceled(this.Token) : this.TrySetResult(new VoidTaskResult()))) 
     return; 
    if (this.Timer != null) 
     this.Timer.Dispose(); 
    this.Registration.Dispose(); 
    } 
} 

Używa timera, ale nie wydaje mi się to martwić. Timer po prostu oddzwoni do kompletnej metody, a to, co robi, to sprawdzenie, czy jest anulowane, jeśli tak, to anuluj, w przeciwnym razie po prostu zwróć wynik. Wydaje mi się to w porządku.

+1

Jestem rzeczywiście zaskoczony, że tworzy nowy obiekt timera dla każdego opóźnienia Myślałem, że użyje kolejki delta z jednym timerem –

+0

Jak wspomniano w dokumentacji MSDN: "System.Threading.Timer jest prostym, lekkim timerem, który używa metod wywołania zwrotnego i jest obsługiwany przez wątki threadpool." Do mnie " lekkość "i" wątki wątków "wydają się być niekompatybilnymi pojęciami –

+0

To rzeczywiście trochę dziwne, że gdy istnieje możliwość wyboru pomiędzy Sleep() a wywołaniem timera, niektórzy programiści zdają się nalegać, aby dodatkowe komunikaty inter-thread i kontekst Zmiany są preferowanym rozwiązaniem: –

Powiązane problemy