System.Timers.Timer vs System.Threading.Timer

565

Ich habe in letzter Zeit einige der möglichen Timer Check - out, und System.Threading.Timerund System.Timers.Timersind diejenigen , die mir notwendig aussehen (da sie Threadpooling unterstützen).

Ich mache ein Spiel und plane, alle Arten von Ereignissen mit unterschiedlichen Intervallen usw. zu verwenden.

Welches wäre das Beste?

TheAJ
quelle

Antworten:

363

Dieser Artikel bietet eine ziemlich umfassende Erklärung:

" Vergleichen der Timer-Klassen in der .NET Framework-Klassenbibliothek " - auch als .chm-Datei verfügbar

Der spezifische Unterschied scheint darin zu liegen, dass er System.Timers.Timerauf Multithread-Anwendungen ausgerichtet ist und daher über seine SynchronizationObjectEigenschaft System.Threading.Timerthreadsicher ist , während er ironischerweise nicht sofort threadsicher ist.

Ich glaube nicht, dass es einen Unterschied zwischen den beiden gibt, da es darum geht, wie klein Ihre Intervalle sein können.

David Andres
quelle
69
Ich denke, dieser Auszug ist aufschlussreich: "Im Gegensatz zum System.Windows.Forms.Timer ruft die System.Timers.Timer-Klasse standardmäßig Ihren Timer-Ereignishandler für einen Arbeitsthread auf, der aus dem Thread-Pool der Common Language Runtime (CLR) abgerufen wurde [...] Die System.Timers.Timer-Klasse bietet eine einfache Möglichkeit, dieses Dilemma zu lösen. Sie macht eine öffentliche SynchronizingObject-Eigenschaft verfügbar. Durch Festlegen dieser Eigenschaft für eine Instanz eines Windows Form (oder eines Steuerelements in einem Windows Form) wird dies der Fall sein Stellen Sie sicher, dass der Code in Ihrem Elapsed-Ereignishandler auf demselben Thread ausgeführt wird, auf dem das SynchronizingObject instanziiert wurde. "
Mico
7
Nach dem Thema Sicherheit Abschnitt in Threading.Timer‚s MSDN - Artikel , ist es perfekt Thread-sicher ...
Pieter
62
System.Threading.Timerist so "ironisch" nicht threadsicher wie System.Threading.Threadund die durch den Pool erhaltenen Threads. Nur weil diese Klassen Ihre Hand nicht halten und die Verwendung des lockSchlüsselworts selbst verwalten, bedeutet dies nicht, dass diese Klassen nicht threadsicher sind. Man könnte genauso gut sagen System.Threading.Thread, dass es nicht threadsicher ist, weil es genau so wahr ist.
Kirk Woll
8
Auch System.Timer.Timer Intervall kann nur Int32 System.Threading.Timer Intervall kann bis zu Int64
Brent
11
Es ist bedauerlich, dass diese höchst irreführende (bestenfalls) Antwort akzeptiert und so hoch bewertet wird. Die einzige wesentliche Aussage in der Antwort selbst ist einfach falsch. Das SynchronizingObjectmacht das Timer-Objekt selbst nicht threadsicher. Es wird lediglich sichergestellt, dass Ihr Code zur Behandlung des Timer-Ereignisses in einem bestimmten Thread aufgerufen wird (wenn Sie diese Eigenschaft entsprechend festlegen). Das Timer-Objekt selbst ist nicht garantiert threadsicher, wie in der Dokumentation klar angegeben. Auf der anderen Seite, das System.Threading.TimerObjekt wird als threadsicher spezifisch dokumentiert.
Peter Duniho
169

System.Threading.Timerist ein einfacher Timer. Es ruft Sie in einem Thread-Pool-Thread (aus dem Worker-Pool) zurück.

System.Timers.Timerist a System.ComponentModel.Component, das a umschließt System.Threading.Timerund einige zusätzliche Funktionen bietet, die zum Versenden auf einem bestimmten Thread verwendet werden.

System.Windows.Forms.TimerUmschließt stattdessen einen nativen Nur-Nachrichten-HWND und verwendet Fenster -Timer , um Ereignisse in dieser HWND-Nachrichtenschleife auszulösen.

Wenn Ihre App keine Benutzeroberfläche hat und Sie einen möglichst leichten und universellen .Net-Timer wünschen (weil Sie gerne Ihr eigenes Threading / Dispatching herausfinden), System.Threading.Timerist dies so gut wie im Framework.

Ich bin mir nicht ganz sicher, was die angeblichen "nicht threadsicheren" Probleme System.Threading.Timersind. Vielleicht ist es genau das Gleiche wie in dieser Frage gestellt: Thread-Sicherheit von System.Timers.Timer vs System.Threading.Timer , oder vielleicht meint jeder nur das:

  1. Es ist einfach, Rennbedingungen zu schreiben, wenn Sie Timer verwenden. Siehe zB folgende Frage: Timer (System.Threading) Thread-Sicherheit

  2. Wiedereintritt von Timer-Benachrichtigungen, bei denen Ihr Timer-Ereignis Sie ein zweites Mal auslösen und zurückrufen kann, bevor Sie die Verarbeitung des ersten Ereignisses abgeschlossen haben. Siehe beispielsweise diese Frage: Thread-sichere Ausführung mit System.Threading.Timer und Monitor

Tim Lovell-Smith
quelle
Richtig das System.Timers.Timerverwendet ein System.Threading.Timerinternes. Siehe Quellcode .
Stomy
120

In seinem Buch " CLR Via C # " rät Jeff Ritcher davon ab System.Timers.Timer, diesen Timer System.ComponentModel.Componentzu verwenden, damit er in der Designoberfläche von Visual Studio verwendet werden kann. Damit wäre es nur sinnvoll, wenn Sie einen Timer auf einer Designoberfläche haben möchten.

Er bevorzugt die Verwendung System.Threading.Timerfür Hintergrundaufgaben in einem Thread-Pool-Thread.

Held
quelle
36
Es kann in einer Designoberfläche verwendet werden - das bedeutet nicht, dass es sein muss, und es gibt keine nachteiligen Auswirkungen, wenn Sie dies nicht tun. Wenn Sie den Artikel in der früheren Antwort auf diese Frage lesen, scheint der Timers.Timer Threading.Timer viel vorzuziehen.
Stephen Drew
6
Was vorzuziehen ist, hängt vom Kontext ab, oder? Soweit ich weiß, führt System.Threading.Timer den übergebenen Rückruf für einen neuen Arbeitsthread von ThreadPool aus. Ich nehme an, das ist auch der Grund, warum es nicht unbedingt threadsicher ist. Ein bisschen macht Sinn. Theoretisch müssten Sie sich also keine Gedanken über das Grunzen machen, Ihren eigenen Arbeitsthread zu spinnen, da dieser Timer dies für Sie erledigt. Ein bisschen lächerlich lächerlich.
Finster
6
Die Verwendung System.Threading.Timerentspricht der Verwendung eines Thread-Pools oder der Erstellung eines eigenen Threads. Von natürlich diese Klassen behandeln nicht die Synchronisation für Sie - das ist Ihre Aufgabe! Weder ein Thread-Pool-Thread, Ihr eigener Thread noch ein Timer-Rückruf übernehmen das Sperren - für welches Objekt und auf welche Weise und unter welchen Umständen Sie sperren müssen, ist ein gutes Urteilsvermögen erforderlich, und die Threading-Version des Timers bietet Ihnen die größte Flexibilität und Flexibilität Die Granularität.
Kirk Woll
2
-1 Diese Antwort ist von Anfang an subjektiv oder unvoreingenommen und bietet keine konkreten Informationen darüber, warum System.Threading.Timer von Jeff Ritcher
Brian Ogden
42

Informationen von Microsoft dazu (siehe Anmerkungen zu MSDN ):

  • System.Timers.Timer , das ein Ereignis auslöst und den Code in regelmäßigen Abständen in einer oder mehreren Ereignissenken ausführt. Die Klasse ist zur Verwendung als serverbasierte oder Dienstkomponente in einer Multithread-Umgebung vorgesehen. Es hat keine Benutzeroberfläche und ist zur Laufzeit nicht sichtbar.
  • System.Threading.Timer , das in regelmäßigen Abständen eine einzelne Rückrufmethode für einen Thread-Pool-Thread ausführt. Die Rückrufmethode wird definiert, wenn der Timer instanziiert wird und nicht geändert werden kann. Wie die System.Timers.Timer-Klasse ist diese Klasse für die Verwendung als serverbasierte oder Dienstkomponente in einer Multithread-Umgebung vorgesehen. Es hat keine Benutzeroberfläche und ist zur Laufzeit nicht sichtbar.
  • System.Windows.Forms.Timer (nur .NET Framework), eine Windows Forms-Komponente, die ein Ereignis auslöst und den Code in regelmäßigen Abständen in einer oder mehreren Ereignissenken ausführt. Die Komponente hat keine Benutzeroberfläche und ist für die Verwendung in einer Single-Thread-Umgebung konzipiert. Es wird auf dem UI-Thread ausgeführt.
  • System.Web.UI.Timer (nur .NET Framework), eine ASP.NET-Komponente, die in regelmäßigen Abständen asynchrone oder synchrone Webseiten-Postbacks durchführt.

Es ist interessant zu erwähnen, dass dies System.Timers.Timermit .NET Core 1.0 veraltet war, aber in .NET Core 2.0 (/ .NET Standard 2.0) erneut implementiert wurde. Das Ziel von .NET Standard 2.0 war, dass es so einfach wie möglich sein sollte, von .NET Framework zu wechseln, was wahrscheinlich der Grund dafür ist, dass es zurückkam.

Wenn es veraltet war, wurde empfohlen, stattdessen das Visual Studio-Add-In von .NET Portability Analyzer zu verwenden System.Threading.Timer.

Microsoft hat das schon System.Threading.Timerfrüher bevorzugt System.Timers.Timer.

BEARBEITUNGSHINWEIS 2018-11-15: Ich möchte meine Antwort ändern, da die alten Informationen zu .NET Core 1.0 nicht mehr gültig waren.

ice1e0
quelle
2
Es scheint wahr zu sein: github.com/npgsql/npgsql/issues/471#issuecomment-94104090
Marco Sulla
@Taegost, seine Verwendung ist ebenfalls begrenzt - siehe MSDN msdn.microsoft.com/en-us/library/… und lesen Sie die Anmerkungen zur Verfügbarkeit der Plattform.
Astrowalker
@astrowalker - Danke dafür, als ich den Kommentar machte, hatte diese Antwort fast kein Detail. Da es jetzt das Detail enthält, nach dem ich gefragt habe, habe ich meinen Kommentar gelöscht.
Taegost
1
System.Timers.Timer wird jetzt in .NET Standard 2.0 und .NET Core 2.0 und höher unterstützt. docs.microsoft.com/en-us/dotnet/api/system.timers.timer (zum Ende des Artikels scrollen)
Lee Grissom
Für diese Antwort gibt es auch System.Windows.Threading.DispatcherTimer .
SpeedCoder5
39

Ein wichtiger Unterschied, der oben nicht erwähnt wurde und Sie System.Timers.Timerauffallen könnte, ist, dass Ausnahmen stillschweigend verschluckt werden, während System.Threading.Timerdies nicht der Fall ist.

Zum Beispiel:

var timer = new System.Timers.Timer { AutoReset = false };
timer.Elapsed += (sender, args) =>
{
    var z = 0;
    var i = 1 / z;
};
timer.Start();

vs.

var timer = new System.Threading.Timer(x =>
{
    var z = 0;
    var i = 1 / z;
}, null, 0, Timeout.Infinite);
stovroz
quelle
1
Ich habe dieses Problem kürzlich mit Timers.Timer festgestellt und es war sehr schmerzhaft ... Irgendwelche Ideen, wie ich mit Threading.Timer umschreiben könnte? stackoverflow.com/questions/41618324/…
Tez Wingfield
7
Der Quellcode enthält einen leeren Haken. Sehen Sie den System.Timers.Timer-Quellcode hier
stomy
Omgsh, warum MS-Programmierer nicht in der Lage sind, dieselben Dinge wirklich gleich zu tun?
Xmedeko
2
Das Beispiel erklärt nicht, wie einer Ausnahmen verschluckt und der andere nicht. Könnte jemand bitte die Details eintragen?
Sean
24

Ich habe einen kurzen Vergleich von MSDN gefunden

Die .NET Framework-Klassenbibliothek enthält vier Klassen mit dem Namen Timer, von denen jede unterschiedliche Funktionen bietet:

System.Timers.Timer, der ein Ereignis auslöst und den Code in regelmäßigen Abständen in einer oder mehreren Ereignissenken ausführt. Die Klasse ist zur Verwendung als serverbasierte oder Dienstkomponente in einer Multithread-Umgebung vorgesehen. Es hat keine Benutzeroberfläche und ist zur Laufzeit nicht sichtbar.

System.Threading.Timer, die in regelmäßigen Abständen eine einzelne Rückrufmethode für einen Thread-Pool-Thread ausführt. Die Rückrufmethode wird definiert, wenn der Timer instanziiert wird und nicht geändert werden kann. Wie die System.Timers.Timer-Klasse ist diese Klasse für die Verwendung als serverbasierte oder Dienstkomponente in einer Multithread-Umgebung vorgesehen. Es hat keine Benutzeroberfläche und ist zur Laufzeit nicht sichtbar.

System.Windows.Forms.Timer, eine Windows Forms-Komponente, die ein Ereignis auslöst und den Code in regelmäßigen Abständen in einer oder mehreren Ereignissenken ausführt. Die Komponente hat keine Benutzeroberfläche und ist für die Verwendung in einer Single-Thread-Umgebung konzipiert.

System.Web.UI.Timer, eine ASP.NET-Komponente, die in regelmäßigen Abständen asynchrone oder synchrone Webseiten-Postbacks durchführt.

Standard
quelle
1

Die beiden Klassen sind funktional äquivalent, außer dass System.Timers.Timereine Option zum Aufrufen aller Timer- Ablaufrückrufe über ISynchronizeInvoke durch Festlegen von SynchronizingObject besteht . Andernfalls rufen beide Timer Ablaufrückrufe für Thread-Pool-Threads auf.

Wenn Sie a System.Timers.Timerauf eine Windows Forms-Entwurfsoberfläche ziehen, setzt Visual Studio SynchronizingObject auf das Formularobjekt, wodurch alle Ablaufrückrufe im UI-Thread aufgerufen werden.

Edward Brey
quelle
1

Von MSDN: System.Threading.Timerist ein einfacher, leichter Timer, der Rückrufmethoden verwendet und von Thread-Pool-Threads bereitgestellt wird. Es wird für die Verwendung mit Windows Forms nicht empfohlen, da die Rückrufe im Thread der Benutzeroberfläche nicht auftreten. System.Windows.Forms.Timerist eine bessere Wahl für die Verwendung mit Windows Forms. Für die serverbasierte Timer-Funktionalität können Sie die Verwendung in Betracht ziehen System.Timers.Timer, die Ereignisse auslöst und zusätzliche Funktionen bietet.

Quelle

Greg Gum
quelle