2017-12-06 1 views
3

Ich habe zufällig eine Intellisense-Tool-Tipp bezüglich des Parameters an System.Threading.Thread.Sleep(int millisecondsTimeout) übergeben, etwas wie "(...) Geben Sie System.Threading.Timeout.Infinite, um den Thread unbegrenzt zu blockieren". Und ich bin fasziniert.Was wäre ein Anwendungsfall für Thread.Sleep (Timeout.Infinite)?

Ich kann verstehen, warum man kurze inaktive Verzögerungen innerhalb einer möglicherweise endlosen Schleife einschließen kann, wodurch andere ausführende Threads Verarbeitungsleistung erhalten, wenn keine sofortige Aktion im schlafenden Thread erforderlich ist, obwohl ich typischerweise die Implementierung solcher Verzögerungen mit EventWaitHandler s vorziehe dass ich vermeiden kann, auf eine volle Verzögerung zu warten, wenn ich dem Thread signalisiere, seine Ausführung aus einem anderen Thread zu beenden.

Aber ich kann nicht sehen, wann ich einen Thread auf unbestimmte Zeit anhalten muss, und auf eine Weise, die, soweit ich das beurteilen kann, nur durch ein ziemlich unscharfes Paar unterbrochen werden kann.

Also, was wäre ein Arbeitsszenario, wo ich einen Thread auf unbestimmte Zeit anhalten könnte?

+0

Vielleicht in einer Workflow-bezogenen Aufgabe? Es kann einen Job geben, den Sie einmal im Jahr (oder auf Ad-hoc-Basis) erledigen müssen, und Sie werden erwarten, dass eine Aufgabe (Teil des Workflows) an diesem Jahrestag erscheint, sodass Sie sie bis zu diesem Zeitpunkt schlafen legen würden. Nicht ein ideales Szenario, sondern nur versuchen zu sehen, wo Sie so lange brauchen würden. – kevchadders

Antwort

2

können Sie verwenden .Interrupt() zu wake ein schlafenden Gewinde (verursacht ThreadInterruptedException in dem Code, die .Sleep() rufen, die abgefangen und behandelt werden können), so dass dies bietet einen Mechanismus zu sagen: „Schlaf, bis jemand stupst Sie“ . Ich sage nicht, dass es notwendigerweise der beste Mechanismus für dieses ist, aber: es kann Gebrauch für Sie haben.

+0

Danke Marc, ich hatte nicht bemerkt, dass es eine Interrupt-Funktion gab. Würde der Aufruf von Thread.Sleep (Infinite) in einem Try/Catch-Block, der ThreadInterruptExceptions verarbeitet und der Aufruf von .Interrupt() von einem anderen Thread ausgeht, funktional dem Aufruf von WaitOne (Infinite) im schlafenden Thread entsprechen und das Ereignis von a signieren anderes Thema? Letzteres scheint sauberer zu sein. –

9

Es ist eine ziemlich lange Geschichte und ich muss meine Hände ein wenig winken, um es verständlich zu machen. Die meisten Programmierer denken, dass Thread.Sleep() den Thread in den Ruhezustand versetzt und verhindert, dass Code ausgeführt wird. Dies ist nicht korrekt. Thread.Sleep (Infinite) entspricht Application.Run(). Im Ernst.

Dies passiert nicht sehr oft im wirklichen Leben, es ist vor allem in benutzerdefinierten Hosting-Szenarien relevant. Das Bereitstellen von Code zum Ausführen in einem bestimmten Thread ist im Allgemeinen ein wichtiges Feature, um mit Code umzugehen, der nicht threadsicher ist und der Hauptgrund dafür, dass Application.Run() existiert. Aber Windows macht einen anderen Weg, um auf einer viel niedrigeren Ebene zu tun, die zugrunde liegende API dafür ist QueueUserAPC(). Das .NET-Analogon dieser Funktion ist BeginInvoke().

Dies erfordert die Zusammenarbeit des Threads, genau wie beim Aufruf von Application.Run(). Der Thread muss sich in einem "warnbaren Wartezustand" befinden und eine blockierende Funktion ausführen, die unterbrochen werden kann. Die CLR führt den Ruhezustand nicht selbst aus, sie übergibt den Job an die CLR host. Die meisten Hosts führen einfach SleepEx() aus und übergeben TRUE für das Argument bAlertable. Der Thread ist jetzt in einem Zustand, um alle von QueueUserAPC() geposteten Anfragen auszuführen. Genau wie es sein wird, wenn es in der Application.Run() - Dispatcher-Schleife aktiv ausgeführt wird.

Die Kernel-Funktion ist sonst im Framework überhaupt nicht verfügbar. Es ist die Art von Code, die sehr schwer zu korrigieren ist, Re-Entrancy Bugs sind ziemlich böse. Wie die meisten Programmierer, die von Application.DoEvents() gebissen wurden oder eine schlecht platzierte MessageBox.Show() attestieren können. Es ist jedoch ein gültiges Szenario in einem benutzerdefinierten Hosting-Szenario. Mit diesem Mechanismus kann der Host C# -Code für die Ausführung in einem bestimmten Thread abrufen. Es ist also möglich, Infinite zu übergeben, da die Designer dieses Szenario nicht absichtlich deaktivieren wollten. Wenn dies vom Gastautor überhaupt möglich gemacht wird, haben sie Sie darüber informiert. Ich kenne kein praktisches Beispiel.

Praktischer, verwenden Sie diese Funktion jeden Tag. Auf diese Weise werden System.Threading.Timer und System.Timers.Timer implementiert.Erledigt durch einen Thread innerhalb der CLR, der gestartet wird, sobald Sie einen Timer verwenden, verwendet er SleepEx(INFINITE, TRUE) in seinem Kern.

+0

Danke Hans für deine Antwort. Es geht nicht ganz auf meine Frage ein (es sei denn, Sie schlagen vor, dass ein Anwendungsfall, den ich finden kann, ist, wenn ich mich entscheide, meine eigene Timer-Klasse zu implementieren), aber es ist dennoch interessant; Ich wünschte, du hättest die längere Antwort nehmen können. Ich bin jedoch von einem Teil Ihrer Antwort noch fasziniert. Sie erwähnen, dass Thread.Sleep (Infinite) gleichbedeutend mit Application.Run() ist und ich denke, dass ich das in dem Sinne sehe, dass beide Aufrufe blockieren, die nicht ganz so blockierend sind, wie man denken würde. (Fortsetzung) –

+0

(Fortsetzung) Während Application.Run() jedoch eine Windows-Meldungsschleife eingibt, ermöglicht es mir, Code in demselben Thread auszuführen, ohne den Aufruf von Application.Run() zu beenden, so weit ich es verstehe, Thread .Sleep (Infinite) lässt mich Callback-Funktionen im selben Thread nicht ausführen, bevor der Aufruf von Thread.Sleep beendet wird. Danke noch einmal! –

+0

Ich schrieb die Antwort vollständig auf das Feature konzentriert, das * es * ermöglicht, Callback-Funktionen auf dem gleichen Thread auszuführen. Ich wünschte, ich könnte Ihnen ein besseres Beispiel geben, benutzerdefinierte Hosts sind jedoch nie gut dokumentiert. –

Verwandte Themen