Läuft ein System.Timers.Timer in einem anderen Thread als dem Thread ab, der ihn erstellt hat?
Nehmen wir an, ich habe eine Klasse mit einem Timer, der alle 5 Sekunden ausgelöst wird. Wenn der Timer ausgelöst wird, wird in der abgelaufenen Methode ein Objekt geändert. Nehmen wir an, das Ändern dieses Objekts dauert lange, beispielsweise 10 Sekunden. Ist es möglich, dass ich in diesem Szenario auf Thread-Kollisionen stoße?
c#
multithreading
timer
user113164
quelle
quelle
Antworten:
Für System.Timers.Timer :
Siehe Brian Gideons Antwort unten
Für System.Threading.Timer :
In der MSDN-Dokumentation zu Timern heißt es:
Der Timer läuft also tatsächlich auf einem anderen Thread ab.
quelle
Es hängt davon ab, ob. Der
System.Timers.Timer
hat zwei Betriebsarten.Wenn
SynchronizingObject
eineISynchronizeInvoke
Instanz festgelegt ist, wird dasElapsed
Ereignis auf dem Thread ausgeführt, auf dem sich das Synchronisierungsobjekt befindet. Normalerweise sind dieseISynchronizeInvoke
Instanzen nichts anderes als alteControl
undForm
Instanzen, mit denen wir alle vertraut sind. In diesem Fall wird dasElapsed
Ereignis im UI-Thread aufgerufen und verhält sich ähnlich wie dasSystem.Windows.Forms.Timer
. Ansonsten hängt es wirklich von der spezifischenISynchronizeInvoke
Instanz ab, die verwendet wurde.Wenn
SynchronizingObject
null ist, wird dasElapsed
Ereignis in einemThreadPool
Thread aufgerufen und verhält sich ähnlich wie dasSystem.Threading.Timer
. Tatsächlich verwendet es einenSystem.Threading.Timer
Blick hinter die Kulissen und führt den Marshalling-Vorgang aus, nachdem es bei Bedarf den Timer-Rückruf erhalten hat.quelle
System.Threading.Timer
oder verwendenSystem.Timers.Timer
?System.Timers.Timer
hat zwei Betriebsarten. Es kann auf einem zufällig zugewiesenen Thread-Pool-Thread oder auf einem beliebigen Thread ausgeführt werden, auf dem sich dieISynchronizeInvoke
Instanz befindet. Ich weiß nicht, wie ich das klarer machen soll.System.Threading.Timer
hat wenig (wenn überhaupt) mit der ursprünglichen Frage zu tun.lock
?Jedes verstrichene Ereignis wird im selben Thread ausgelöst, es sei denn, ein vorheriges verstrichenes Ereignis wird noch ausgeführt.
So erledigt es die Kollision für Sie
Versuchen Sie dies in eine Konsole zu setzen
Sie werden so etwas bekommen
Dabei ist 10 der aufrufende Thread und 6 und 12 werden aus dem abgelaufenen bg-Ereignis ausgelöst. Wenn Sie den Thread.Sleep (2000) entfernen; Sie werden so etwas bekommen
Da gibt es keine Kollisionen.
Aber das lässt dich immer noch mit einem Problem zurück. Wenn Sie das Ereignis alle 5 Sekunden auslösen und die Bearbeitung 10 Sekunden dauert, benötigen Sie eine Sperre, um einige Änderungen zu überspringen.
quelle
timer.Stop()
am Anfang der Methode "Verstrichenes Ereignis" und einestimer.Start()
am Ende der Methode "Verstrichenes Ereignis" wird verhindert, dass das Ereignis "Verstrichen" kollidiert.Für System.Timers.Timer in einem separaten Thread, wenn SynchronizingObject nicht festgelegt ist.
Ausgabe, die Sie sehen würden, wenn DummyTimer im Intervall von 5 Sekunden ausgelöst würde:
Wie zu sehen ist, wird OnDummyTimerFired im Workers-Thread ausgeführt.
Nein, weitere Komplikationen - Wenn Sie das Intervall auf 10 ms reduzieren,
Dies liegt daran, dass .NET einen neuen Thread für diesen Job erstellen würde, wenn die vorherige Ausführung von OnDummyTimerFired beim nächsten Häkchen nicht erfolgt.
Erschwerend kommt hinzu: "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 sichergestellt dass der Code in Ihrem Elapsed-Ereignishandler auf demselben Thread ausgeführt wird, auf dem das SynchronizingObject instanziiert wurde. "
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx#S2
quelle
Wenn das abgelaufene Ereignis länger als das Intervall dauert, wird ein weiterer Thread erstellt, um das abgelaufene Ereignis auszulösen. Dafür gibt es jedoch eine Problemumgehung
quelle