Je vois souvent qu'il est mentionné que cela Thread.Sleep();
ne devrait pas être utilisé, mais je ne comprends pas pourquoi. Si cela Thread.Sleep();
peut causer des problèmes, existe-t-il des solutions alternatives avec le même résultat qui seraient sûres?
par exemple.
while(true)
{
doSomework();
i++;
Thread.Sleep(5000);
}
un autre est:
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
la source
la source
goto:
s'il y a probablement une meilleure solution à vos problèmes queSleep
.goto
, qui ressemble plus à une odeur de code qu'à une odeur de design. Il n'y a rien de mal à ce qu'un compilateur insère desgoto
s dans votre code: l'ordinateur ne se confond pas. Mais ceThread.Sleep
n'est pas exactement la même chose; les compilateurs n'insèrent pas cet appel et cela a d'autres conséquences négatives. Mais oui, le sentiment général selon lequel son utilisation est erronée car il y a presque toujours une meilleure solution est certainement correct.sleep()
du code (ou des tests), un chiot meurtRéponses:
Les problèmes liés à l'appel
Thread.Sleep
sont expliqués assez succinctement ici :La solution préférée: WaitHandles
L'erreur la plus commise est d'utiliser
Thread.Sleep
avec une construction while ( démo et réponse , belle entrée de blog )EDIT:
Je voudrais améliorer ma réponse:
la source
SCÉNARIO 1 - attendre la fin de la tâche asynchrone: je suis d'accord que WaitHandle / Auto | ManualResetEvent doit être utilisé dans le scénario où un thread attend la fin de la tâche sur un autre thread.
SCENARIO 2 - timing while loop: Cependant, comme un mécanisme de timing brut (while + Thread.Sleep) est parfaitement bien pour 99% des applications qui ne nécessitent PAS de savoir exactement quand le Thread bloqué doit "se réveiller *. L'argument qu'il prend 200k cycles pour créer le thread sont également invalides - le thread de la boucle de synchronisation doit quand même être créé et 200k cycles est juste un autre grand nombre (dites-moi combien de cycles pour ouvrir un fichier / socket / db appels?).
Donc, si while + Thread.Sleep fonctionne, pourquoi compliquer les choses? Seuls les juristes de la syntaxe seraient pratiques !
la source
Je voudrais répondre à cette question du point de vue de la politique de codage, qui peut être utile ou non à quiconque. Mais en particulier lorsque vous avez affaire à des outils destinés aux programmeurs d'entreprise 9 à 5, les personnes qui rédigent de la documentation ont tendance à utiliser des mots tels que «ne devrait pas» et «ne jamais» signifier «ne faites pas cela à moins que vous ne sachiez vraiment ce que vous faites et pourquoi ".
Quelques-uns de mes autres favoris dans le monde C # sont qu'ils vous disent de "ne jamais appeler lock (this)" ou "ne jamais appeler GC.Collect ()". Ces deux sont déclarés avec force dans de nombreux blogs et dans la documentation officielle, et l'OMI est une désinformation complète. À un certain niveau, cette désinformation sert son objectif, en ce qu'elle empêche les débutants de faire des choses qu'ils ne comprennent pas avant de rechercher complètement les alternatives, mais en même temps, il est difficile de trouver de VRAIES informations via les moteurs de recherche qui semblent pointer vers des articles vous disant de ne pas faire quelque chose tout en n'offrant aucune réponse à la question "pourquoi pas?"
Politiquement, cela se résume à ce que les gens considèrent comme «bon design» ou «mauvais design». La documentation officielle ne doit pas dicter la conception de mon application. S'il y a vraiment une raison technique pour laquelle vous ne devriez pas appeler sleep (), alors la documentation de l'OMI devrait indiquer qu'il est tout à fait acceptable de l'appeler dans des scénarios spécifiques, mais peut-être offrir des solutions alternatives indépendantes du scénario ou plus appropriées pour l'autre. scénarios.
Appeler clairement "sleep ()" est utile dans de nombreuses situations où les délais sont clairement définis en temps réel, cependant, il existe des systèmes plus sophistiqués pour attendre et signaler les threads qui doivent être pris en compte et compris avant de commencer à dormir ( ) dans votre code, et lancer des instructions sleep () inutiles dans votre code est généralement considéré comme une tactique pour les débutants.
la source
C'est la boucle 1) .spinning et 2) .polling de vos exemples que les gens mettent en garde , pas la partie Thread.Sleep (). Je pense que Thread.Sleep () est généralement ajouté pour améliorer facilement le code qui tourne ou dans une boucle d'interrogation, donc il est simplement associé à du «mauvais» code.
De plus, les gens font des choses comme:
où la variable inWait n'est pas accessible de manière thread-safe, ce qui pose également des problèmes.
Ce que les programmeurs veulent voir, ce sont les threads contrôlés par les constructions Events et Signalisation et Verrouillage, et lorsque vous faites cela, vous n'aurez pas besoin de Thread.Sleep (), et les préoccupations concernant l'accès aux variables thread-safe sont également éliminées. À titre d'exemple, pourriez-vous créer un gestionnaire d'événements associé à la classe FileSystemWatcher et utiliser un événement pour déclencher votre deuxième exemple au lieu d'une boucle?
Comme l'a mentionné Andreas N., lisez Threading en C #, de Joe Albahari , c'est vraiment très bien.
la source
Thread.Sleep()
avec une autre fonction et l'appeler dans la boucle while?Sleep est utilisé dans les cas où des programmes indépendants sur lesquels vous n'avez aucun contrôle peuvent parfois utiliser une ressource couramment utilisée (par exemple, un fichier), à laquelle votre programme doit accéder lorsqu'il s'exécute et lorsque la ressource est utilisée par ces derniers. d'autres programmes, votre programme ne peut pas l'utiliser. Dans ce cas, où vous accédez à la ressource dans votre code, vous placez votre accès à la ressource dans un try-catch (pour attraper l'exception lorsque vous ne pouvez pas accéder à la ressource), et vous mettez cela dans une boucle while. Si la ressource est gratuite, le sommeil n'est jamais appelé. Mais si la ressource est bloquée, vous dormez pendant un laps de temps approprié et essayez à nouveau d'accéder à la ressource (c'est pourquoi vous faites une boucle). Cependant, gardez à l'esprit que vous devez mettre une sorte de limiteur sur la boucle, donc ce n'est pas une boucle potentiellement infinie.
la source
J'ai un cas d'utilisation que je ne vois pas tout à fait couvert ici, et je soutiendrai que c'est une raison valable d'utiliser Thread.Sleep ():
Dans une application console exécutant des tâches de nettoyage, je dois effectuer un grand nombre d'appels de base de données assez coûteux, vers une base de données partagée par des milliers d'utilisateurs simultanés. Afin de ne pas marteler la base de données et d'exclure les autres pendant des heures, j'aurai besoin d'une pause entre les appels, de l'ordre de 100 ms. Ceci n'est pas lié au timing, mais simplement à l'accès à la base de données pour d'autres threads.
Dépenser 2000-8000 cycles sur la commutation de contexte entre les appels qui peuvent prendre 500 ms pour s'exécuter est bénin, tout comme le fait d'avoir 1 Mo de pile pour le thread, qui s'exécute comme une seule instance sur un serveur.
la source
Thread.Sleep
dans une application console à un seul thread et à usage unique comme celle que vous décrivez est parfaitement OK.Je suis d'accord avec beaucoup ici, mais je pense aussi que cela dépend.
Récemment, j'ai fait ce code:
C'était une simple fonction d'animation, et je l'ai utilisée
Thread.Sleep
.Ma conclusion, si cela fait le travail, utilisez-le.
la source
Pour ceux d'entre vous qui n'ont pas vu d'argument valable contre l'utilisation de Thread.Sleep dans SCENARIO 2, il y en a vraiment un - la sortie de l'application est bloquée par la boucle while (SCENARIO 1/3 est tout simplement stupide, donc pas digne de plus mentionnant)
Beaucoup de ceux qui prétendent être au courant, criant Thread.leep is evil n'ont pas mentionné une seule raison valable pour ceux d'entre nous qui exigeaient une raison pratique de ne pas l'utiliser - mais la voici, grâce à Pete - Thread. is Evil (peut être facilement évité avec un timer / handler)
la source
Thread.Sleep
n'est pas la raison (le nouveau thread et la boucle while continue est)! vous pouvez simplement supprimer laThread.Sleep
-line - et voilà: le programme ne se fermera pas aussi ...