Frage

Ich schreibe eine App, die genutzt werden muss Timers, aber möglicherweise sehr viele davon.Wie skalierbar ist die System.Threading.Timer Klasse?In der Dokumentation heißt es lediglich, es sei „leicht“, aber es wird nicht weiter darauf eingegangen.Werden diese Timer in einen einzelnen Thread (oder einen sehr kleinen Threadpool) gesaugt, der alle Rückrufe im Namen eines verarbeitet? Timer, oder tut es jedes Timer einen eigenen Thread haben?

Ich denke, eine andere Möglichkeit, die Frage umzuformulieren, ist:Wie ist System.Threading.Timer umgesetzt?

War es hilfreich?

Lösung

Ich sage dies als Antwort auf viele Fragen:Vergessen Sie nicht, dass der (verwaltete) Quellcode des Frameworks verfügbar ist.Mit diesem Tool können Sie alles bekommen: http://www.codeplex.com/NetMassDownloader

Leider ist in diesem speziellen Fall ein Großteil der Implementierung in nativem Code, sodass Sie keinen Blick darauf werfen können ...

Sie verwenden jedoch definitiv Pool-Threads und keinen Thread-pro-Timer.

Die Standardmethode zum Implementieren einer großen Sammlung von Timern (so macht es der Kernel intern, und ich würde vermuten, dass Ihre große Sammlung von Timern dadurch indirekt endet), besteht darin, die Liste nach Zeit bis zum Ablauf sortiert zu halten – also die Das System muss sich immer nur um die Überprüfung des nächsten Timers kümmern, der abläuft, nicht um die gesamte Liste.

Dies ergibt grob gesagt O(log n) für den Start eines Timers und O(1) für die Verarbeitung laufender Timer.

Bearbeiten:Ich habe gerade in Jeff Richters Buch nachgeschaut.Er sagt (von Threading.Timer), dass es einen einzelnen Thread für alle Timer-Objekte verwendet, dieser Thread weiß, wann der nächste Timer (d. h.wie oben) ist fällig und ruft gegebenenfalls ThreadPool.QueueUserWorkItem für die Rückrufe auf.Dies hat zur Folge, dass Ihr Rückruf in einem anderen Pool-Thread erneut eingegeben wird, wenn Sie die Bearbeitung eines Rückrufs für einen Timer nicht beenden, bevor der nächste fällig ist.Zusammenfassend bezweifle ich also, dass Sie ein großes Problem mit vielen Timern sehen werden, aber es kann zu einer Erschöpfung des Thread-Pools kommen, wenn eine große Anzahl davon gleichzeitig mit dem Timer ausgelöst wird und/oder ihre Rückrufe langsam laufen.

Andere Tipps

Ich denke, dass Sie Ihr Design vielleicht überdenken möchten (sofern Sie selbst die Kontrolle über das Design haben).Wenn Sie so viele Timer verwenden, dass dies tatsächlich ein Problem für Sie darstellt, besteht hier eindeutig Potenzial für eine Konsolidierung.

Hier ist ein guter Artikel aus dem MSDN Magazine von vor ein paar Jahren, der die drei verfügbaren Timer-Klassen vergleicht und einige Einblicke in ihre Implementierungen gibt:

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

Konsolidieren Sie sie.Erstellen Sie einen Timer -Dienst und bitten Sie das nach den Timern.Es muss nur einen aktiven Timer behalten (für den nächsten fälligen Anruf) ...

Damit dies eine Verbesserung gegenüber der einfachen Erstellung vieler Threading.Timer-Objekte darstellt, müssen Sie davon ausgehen, dass es nicht genau das ist, was Threading.Timer intern bereits tut.Es würde mich interessieren, wie Sie zu diesem Schluss gekommen sind (ich habe die nativen Teile des Frameworks nicht zerlegt, Sie könnten also durchaus Recht haben).

^^ wie DannySmurf sagt:Konsolidieren Sie sie.Erstellen Sie einen Timer-Dienst und fragen Sie ihn nach den Timern.Es muss lediglich ein aktiver Timer (für den nächsten fälligen Anruf) und ein Verlauf aller Timer-Anfragen gespeichert und dieser bei AddTimer() / RemoveTimer() neu berechnet werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top