Ich sehe oft erwähnt, dass Thread.Sleep();
es nicht verwendet werden sollte, aber ich kann nicht verstehen, warum dies so ist. Wenn Thread.Sleep();
dies zu Problemen führen kann, gibt es alternative Lösungen mit demselben Ergebnis, die sicher wären?
z.B.
while(true)
{
doSomework();
i++;
Thread.Sleep(5000);
}
ein anderer ist:
while (true)
{
string[] images = Directory.GetFiles(@"C:\Dir", "*.png");
foreach (string image in images)
{
this.Invoke(() => this.Enabled = true);
pictureBox1.Image = new Bitmap(image);
Thread.Sleep(1000);
}
}
c#
multithreading
sleep
Burimi
quelle
quelle
goto:
es wahrscheinlich eine bessere Lösung für Ihre Probleme gibt alsSleep
.goto
, was eher einem Code-Geruch als einem Design-Geruch ähnelt. Es ist nichts Falsches daran,goto
wenn ein Compiler s in Ihren Code einfügt : Der Computer wird nicht verwirrt. IstThread.Sleep
aber nicht genau das gleiche; Compiler fügen diesen Aufruf nicht ein und es hat andere negative Konsequenzen. Aber ja, das allgemeine Gefühl, dass es falsch ist, weil es fast immer eine bessere Lösung gibt, ist sicherlich richtig.sleep()
Code (oder Tests) eingeben, stirbt ein WelpeAntworten:
Die Probleme beim Anrufen
Thread.Sleep
werden hier ganz kurz erklärt :Die bevorzugte Lösung: WaitHandles
Der am häufigsten gemachte Fehler ist die Verwendung
Thread.Sleep
eines while-Konstrukts ( Demo und Antwort , netter Blogeintrag ).EDIT:
Ich möchte meine Antwort verbessern:
quelle
SZENARIO 1 - Warten auf den Abschluss einer asynchronen Aufgabe: Ich bin damit einverstanden, dass WaitHandle / Auto | ManualResetEvent in einem Szenario verwendet wird, in dem ein Thread auf die Fertigstellung einer Aufgabe in einem anderen Thread wartet.
SZENARIO 2 - Timing während der Schleife: Als grober Timing-Mechanismus (while + Thread.Sleep) ist er jedoch für 99% der Anwendungen vollkommen in Ordnung, bei denen NICHT genau bekannt sein muss, wann der blockierte Thread "aufwachen" soll. Das Argument, das er benötigt 200k Zyklen zum Erstellen des Threads sind ebenfalls ungültig - der Timing-Loop-Thread muss trotzdem erstellt werden und 200k Zyklen sind nur eine weitere große Zahl (sagen Sie mir, wie viele Zyklen zum Öffnen einer Datei / eines Sockets / einer Datenbank aufgerufen werden sollen?).
Also, wenn + Thread.Sleep funktioniert, warum dann die Dinge komplizieren? Nur Syntaxanwälte wären praktisch !
quelle
Ich möchte diese Frage aus einer kodierungspolitischen Perspektive beantworten, die für niemanden hilfreich sein kann oder nicht. Aber besonders wenn Sie mit Tools arbeiten, die für 9-5 Unternehmensprogrammierer gedacht sind, verwenden Leute, die Dokumentation schreiben, Wörter wie "sollte nicht" und "nie", um zu bedeuten "tun Sie dies nicht, es sei denn, Sie wissen wirklich, was Sie tun tun und warum ".
Einige meiner anderen Favoriten in der C # -Welt sind, dass sie Ihnen sagen, dass Sie "niemals lock (this)" oder "niemals GC.Collect () aufrufen" sollen. Diese beiden werden in vielen Blogs und offiziellen Dokumentationen mit Nachdruck deklariert, und IMO sind vollständige Fehlinformationen. In gewisser Weise erfüllt diese Fehlinformation ihren Zweck, indem sie die Anfänger davon abhält, Dinge zu tun, die sie nicht verstehen, bevor sie die Alternativen vollständig erforscht haben. Gleichzeitig macht es jedoch schwierig, WIRKLICHE Informationen über Suchmaschinen zu finden, die alle scheinen auf Artikel zu verweisen, in denen Sie aufgefordert werden, nichts zu tun, ohne die Frage "Warum nicht?" zu beantworten.
Politisch läuft es darauf hinaus, was die Leute als "gutes Design" oder "schlechtes Design" betrachten. Die offizielle Dokumentation sollte nicht das Design meiner Anwendung bestimmen. Wenn es wirklich einen technischen Grund gibt, warum Sie sleep () nicht aufrufen sollten, sollte IMO in der Dokumentation angegeben werden, dass es völlig in Ordnung ist, es unter bestimmten Szenarien aufzurufen, aber möglicherweise einige alternative Lösungen anbieten, die szenariounabhängig oder für die anderen besser geeignet sind Szenarien.
Das eindeutige Aufrufen von "sleep ()" ist in vielen Situationen nützlich, in denen die Fristen in Echtzeit klar definiert sind. Es gibt jedoch ausgefeiltere Systeme zum Warten und Signalisieren von Threads, die berücksichtigt und verstanden werden sollten, bevor Sie mit dem Schlafen beginnen ( ) in Ihren Code, und unnötige sleep () - Anweisungen in Ihren Code zu werfen, wird im Allgemeinen als Anfängertaktik angesehen.
quelle
Es ist die 1) .spinning- und 2) .polling-Schleife Ihrer Beispiele, vor der die Leute warnen, nicht der Thread.Sleep () -Teil. Ich denke, Thread.Sleep () wird normalerweise hinzugefügt, um Code, der sich dreht oder sich in einer Abfrageschleife befindet, leicht zu verbessern, so dass es nur mit "schlechtem" Code verbunden ist.
Außerdem machen die Leute Sachen wie:
Dabei wird nicht threadsicher auf die Variable inWait zugegriffen, was ebenfalls Probleme verursacht.
Was Programmierer sehen möchten, sind die Threads, die von Events und Signaling and Locking-Konstrukten gesteuert werden. Wenn Sie dies tun, benötigen Sie Thread.Sleep () nicht, und die Bedenken hinsichtlich des thread-sicheren Variablenzugriffs werden ebenfalls beseitigt. Könnten Sie beispielsweise einen Ereignishandler erstellen, der der FileSystemWatcher-Klasse zugeordnet ist, und ein Ereignis verwenden, um Ihr zweites Beispiel auszulösen, anstatt eine Schleife durchzuführen?
Wie Andreas N. erwähnte, lesen Sie Threading in C # von Joe Albahari , es ist wirklich sehr, sehr gut.
quelle
Thread.Sleep()
mit einer anderen Funktion umbrechen und diese in der while-Schleife aufrufen?Sleep wird in Fällen verwendet, in denen unabhängige Programme, auf die Sie keinen Einfluss haben, manchmal eine häufig verwendete Ressource (z. B. eine Datei) verwenden, auf die Ihr Programm zugreifen muss, wenn es ausgeführt wird und wenn die Ressource von diesen verwendet wird andere Programme Ihr Programm ist daran gehindert, es zu verwenden. In diesem Fall, wenn Sie in Ihrem Code auf die Ressource zugreifen, setzen Sie Ihren Zugriff auf die Ressource in einen Try-Catch (um die Ausnahme abzufangen, wenn Sie nicht auf die Ressource zugreifen können) und setzen dies in eine while-Schleife. Wenn die Ressource frei ist, wird der Schlaf nie aufgerufen. Wenn die Ressource jedoch blockiert ist, schlafen Sie eine angemessene Zeit lang und versuchen erneut, auf die Ressource zuzugreifen (aus diesem Grund führen Sie eine Schleife durch). Beachten Sie jedoch, dass Sie eine Art Begrenzer auf die Schleife setzen müssen, damit es sich nicht um eine potenziell unendliche Schleife handelt.
quelle
Ich habe einen Anwendungsfall, den ich hier nicht ganz sehe, und werde argumentieren, dass dies ein gültiger Grund für die Verwendung von Thread.Sleep () ist:
In einer Konsolenanwendung, in der Bereinigungsjobs ausgeführt werden, muss ich eine große Anzahl ziemlich teurer Datenbankaufrufe an eine Datenbank senden, die von Tausenden gleichzeitigen Benutzern gemeinsam genutzt wird. Um die DB nicht zu hämmern und andere stundenlang auszuschließen, benötige ich eine Pause zwischen den Aufrufen in der Größenordnung von 100 ms. Dies hängt nicht mit dem Timing zusammen, sondern nur damit, anderen Threads Zugriff auf die Datenbank zu gewähren.
Es ist harmlos, 2000-8000 Zyklen für die Kontextumschaltung zwischen Aufrufen zu verwenden, deren Ausführung 500 ms dauern kann, ebenso wie 1 MB Stapel für den Thread, der als einzelne Instanz auf einem Server ausgeführt wird.
quelle
Thread.Sleep
in einer Konsolenanwendung mit einem Thread und einem einzigen Zweck wie der von Ihnen beschriebenen ist vollkommen in Ordnung.Ich stimme vielen hier zu, aber ich denke auch, dass es darauf ankommt.
Kürzlich habe ich diesen Code gemacht:
Es war eine einfache Animationsfunktion, die ich verwendet
Thread.Sleep
habe.Mein Fazit: Wenn es den Job macht, benutze es.
quelle
Für diejenigen unter Ihnen, die kein gültiges Argument gegen die Verwendung von Thread.Sleep in SCENARIO 2 gesehen haben, gibt es wirklich eines: Der Anwendungs-Exit wird durch die while-Schleife aufgehalten (SCENARIO 1/3 ist einfach nur dumm, also nicht mehr wert Erwähnung)
Viele, die so tun, als wären sie auf dem Laufenden und schreien Thread.Sleep ist böse, haben keinen einzigen gültigen Grund für diejenigen von uns genannt, die einen praktischen Grund forderten, ihn nicht zu verwenden - aber hier ist es dank Pete - Thread.Sleep ist böse (kann leicht mit einem Timer / Handler vermieden werden)
quelle
Thread.Sleep
ist nicht der Grund dafür (der neue Thread und die kontinuierliche while-Schleife ist)! Sie können einfach dieThread.Sleep
-line entfernen - et voila: das Programm wird nicht so gut beendet ...