2013-06-29 14 views
11

Sto pensando di utilizzare C# async \ await nel server di gioco MMO con logica event-driven. Supponiamo che ci siano migliaia di entità che svolgono un lavoro con durate note. Quindi vorrei invocare Time.Delay() per ogni mio oggetto di gioco. (Questo è un approccio opposto al ciclo infinito comune con qualche chiamata Update() per ogni oggetto di gioco.)Quanto costa utilizzare Task.Delay()?

Qualcuno sa come è implementato lo Task.Delay()? Sta usando i timer? È pesante sulle risorse di sistema?

Va bene generare migliaia di chiamate simultanee Task.Delay()?

+4

@ColeJohnson Perché 'Thread.Sleep' non è' async'? –

+0

E Task.Delay è? Non ha senso. Se voglio ritardare un thread, lo voglio ADESSO, non generare un altro thread per dire a uno di fermarsi. –

+0

@Cole Il punto è fare in modo che un thread attenda un po 'di tempo prima di riprendere. Il punto non è ritardare un thread. –

risposta

17

Task.Delay è implementato come segue:

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; 
} 

utilizza sicuramente timer. Sono utilizzati in una classe chiamata DelayPromise. Ecco l'implementazione per questo:

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(); 
    } 
} 

Utilizza un timer, ma non mi sembra una preoccupazione. Il timer richiama semplicemente il metodo completo, e ciò che fa è controllare se è stato cancellato, in tal caso cancellarlo, altrimenti solo restituire un risultato. Mi sembra soddisfacente.

+1

Sono davvero sorpreso che crei un nuovo oggetto timer per ogni ritardo Avrei pensato che avrebbe usato una coda delta con un timer –

+0

Come detto nella documentazione MSDN: "System.Threading.Timer è un timer semplice e leggero che utilizza metodi di callback ed è servito da thread del threadpool." Per me " lightweightness "e" threadpool thread "sembrano essere concetti incompatibili –

+0

È davvero un po 'strano che, quando c'è una scelta tra Sleep() e una chiamata timer, alcuni sviluppatori sembrano insistere sul fatto che le comunicazioni inter-thread extra e il contesto- le modifiche sono la soluzione preferita –

Problemi correlati