2013-06-29 7 views
11

Ich denke über die Verwendung von C# async \ awa auf dem MMO-Spieleserver mit ereignisgesteuerter Logik. Nehmen wir an, es gibt Tausende von Entitäten, die mit bekannter Dauer arbeiten. Also möchte ich für jedes meiner Spielobjekte Time.Delay() aufrufen. (Dies ist ein gegensätzlicher Ansatz zu gemeinsamen Endlosschleife mit einigen Update() Aufruf für jedes Spielobjekt.)Was kostet es, Task.Delay() zu verwenden?

Weiß jemand wie ist Task.Delay() implementiert? Verwendet es Timer? Ist es schwer auf Systemressourcen?

Ist es in Ordnung, Tausende von simultanen Task.Delay() Invokationen zu spawnen?

+4

@ColeJohnson Weil 'Thread.Sleep' nicht' async' ist? –

+0

Und Task.Delay ist? Das ergibt keinen Sinn. Wenn ich einen Thread verzögern möchte, möchte ich es JETZT, keinen anderen Thread hervorbringen, um einen anzuhalten. –

+0

@Cole Der Punkt ist, einen Thread einige Zeit warten zu lassen, bevor er fortfährt. Es geht nicht darum, einen Thread zu verzögern. –

Antwort

17

Task.Delay wird wie folgt implementiert:

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

Es nutzt definitiv Timer. Sie werden in einer Klasse namens DelayPromise verwendet. Hier ist die Implementierung dafür:

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

Es verwendet einen Timer, aber es scheint nicht wie eine Sorge für mich. Der Timer ruft nur die vollständige Methode auf und überprüft, ob sie abgebrochen wurde. Wenn sie abgebrochen wird, geben Sie einfach ein Ergebnis zurück. Es scheint mir gut zu sein.

+1

Ich bin wirklich überrascht, dass es ein neues Timer-Objekt für jedes Delay erstellt Ich hätte gedacht, es würde einige Delta-Warteschlange mit einem Timer verwenden. –

+0

Wie in der MSDN-Dokumentation gesagt: "System.Threading.Timer ist ein einfacher, leichter Timer, der Callback-Methoden verwendet und von Threadpool-Threads bedient wird." Lightweightness "und" threadpool threads "scheinen inkompatible Konzepte zu sein. –

+0

Es ist in der Tat ein wenig seltsam, dass, wenn es eine Wahl zwischen Sleep() und einem Timer-Aufruf gibt, einige Entwickler darauf bestehen, dass zusätzliche Inter-Thread-Comms und Kontext- Änderungen ist die bevorzugte Lösung. –

Verwandte Themen