Pourquoi est-Fil.Sommeil si dangereux
Je vois souvent mentionné que Thread.Sleep();
ne doit pas être utilisé, mais je ne peux pas comprendre pourquoi il en est ainsi. Si Thread.Sleep();
peut causer des problèmes, existe-il des solutions alternatives avec le même résultat qui serait à l'abri?
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);
}
}
- Pouvez-vous indiquer les références précises? Des preuves anecdotiques ne supporte pas un argument.
- Pour le deuxième paragraphe: qu'essayez-vous de réaliser? (Ou, pourquoi voulez-vous dormir?)
- Un résumé du blog peut-être " n'est pas une mauvaise utilisation de Thread.sleep()'.
- Je ne dirais pas que c'est nocif. Je dirais plutôt que c'est comme
goto:
c'est à dire il y a sans doute une meilleure solution à vos problèmes deSleep
. - Ce n'est pas exactement la même que
goto
, ce qui est plus comme une odeur de code que d'une conception de l'odorat. Il n'y a rien de mal avec un compilateur insertiongoto
s dans votre code: l'ordinateur ne peut pas se confondre. MaisThread.Sleep
n'est pas exactement la même; compilateurs ne pas insérer de cet appel, et il a d'autres conséquences négatives. Mais oui, le sentiment général, à l'aide de c'est mauvais car il n'y a presque toujours une meilleure solution est certainement correct. - c'est ce que j'allait faire 🙂 bon plus si.
- Le sommeil a ses utilise, mais a été utilisé à mauvais escient* et abusé d'un lot (extrêmes 1). Je pense que c'est plus facile pour certains d'essayer de simplement l'interdire (extrêmes 2/l'autre). Cela étant dit, une combinaison de pools de threads + éléments de travail + minuteries/événements vous donnera plus de rendement au coût de codage supplémentaire de temps/lignes de code (au lieu de dormir, ce thread pourrait faire autre chose sans avoir à vous frayer un autre). Mauvaise utilisation: essayez d'exécuter l'un de ces échantillons dans une interface graphique, application, sur principal/thread d'INTERFACE utilisateur -> qui fait Dormir aussi nocif que de la dynamite lorsque vous essayez d'ouvrir une porte, mais bon, pourquoi avez-vous choisi la dynamite?
- Microsoft a suggéré que le Thread.Sleep(n) est nuisible ou ne doit pas être utilisé
- Pourquoi ne peut-fil.sommeil être utilisé dans un long-serveur en cours d'exécution ou gui application de vérifier périodiquement io-demandes,etc?
- utilisez une minuterie ou de la planification de cadre (comme quartz.net) alors...
- Tout le monde est de fournir des avis sur pourquoi les exemples ci-dessus sont mauvais, mais personne n'a fourni une version réécrite à ne pas utiliser de Fil.Sleep() qui encore accomplit le but de les exemples donnés.
- Chaque fois que vous mettez
sleep()
dans le code (ou tests) un chiot meurt - Les réponses ici sont un peu vieux. Aujourd'hui, l'utilisation
Task.Delay
. Voir is-it-always-bad-to-use-thread-sleep - Pardon de mon ignorance. Quel est le but de
this.Invoke(() => this.Enabled = true);
?
Vous devez vous connecter pour publier un commentaire.
Le problème avec l'appel
Thread.Sleep
sont explique très succinctement ici:La solution préférée: WaitHandles
Les plus-fait-erreur à l'aide de
Thread.Sleep
avec un tout-construire (démonstration et répondre à, blog de nice-entrée)EDIT:
Je voudrais améliorer ma réponse:
Thread.Sleep
fait, mais à la fois appel externe-win32-méthodes ... donc un gars avec un win32-fond doit répondre que!while (condition) Thread.Sleep(1000)
, ou encore mieuxwhile (condition);
, construire ... c'est de la conception de l'odorat et devrait être optd avec un WaitHandle de toute façon!Thread.Sleep
ou similaires) 2) nous sommes en attente en raison des changements de condition de quelques temps ... mot-clé(s) temps! si l'état-vérifier dans notre code de domaine, nous devrions utiliser WaitHandles - sinon le composant externe doit fournir une certaine forme de crochets ... si ce n'est pas sa conception, c'est mal! Ma réponse couvre principalement les cas d'utilisation 2 ...Thread.Sleep
ou C# n'est pas la meilleure façon de mettre en œuvre un tel scénario (mais peut-être le plus confortable possible 🙂 )!Thread.Sleep(0)
ne céder à des threads de même ou une plus grande priorité,Thread.Sleep(1)
est nécessaire de céder à une quelconque thread en attente. Sur une machine mono-PROCESSEUR, c'est plus que possible que quelque chose vous appelle justeThread.Sleep(0)
dans ce qui est destiné à être un bref serré spin attendre 3secs pour le thread de priorité faible d'attente pour être stimulé.Thread.Sleep
de a-sa-place-mais-plus-utilise-sont-une-erreur, mais si vous écrivez quelque chose qui n'est pas complètement le contrôle de tous les fils qu'il pourrait peut-être voir ensuite c'est une affaire importante à prendre en compte. Si vous avez à tourner serré (pas en soi quelque chose il faut le faire souvent) avant de l'enfiler.Sleep(0) et maintenant de nouveau et de le jeter dans l'étrange Fil.Sleep(1) si vous avez un seul noyau à utiliser.SCÉNARIO 1 - attendre async l'achèvement de la tâche: je suis d'accord que WaitHandle/Auto|ManualResetEvent devrait être utilisé dans le scénario où un thread est en attente de tâche sur un autre thread pour terminer.
SCÉNARIO 2 - la durée de la boucle: Cependant, comme un brut mécanisme de synchronisation (alors que+Thread.Le sommeil) est parfaitement bien pour 99% des applications qui ne nécessitent PAS de savoir exactement lorsque le Thread bloqué devrait "wake up*. L'argument qu'il faut 200k cycles de la création du thread n'est pas valide - le calendrier de la boucle de fil doit être créée de toute façon et 200k cycles est juste un autre grand nombre (dites-moi combien de cycles pour ouvrir un fichier/socket/db appels?).
Alors si en+Thread.Des travaux de sommeil, pourquoi compliquer les choses? Seule la syntaxe des avocats, serait, pratique!
J'aimerais répondre à cette question à partir d'un codage de la politique de la perspective, qui peut ou peut ne pas être utile à tout le monde. Mais surtout quand vous travaillez avec des outils qui sont destinés à 9-5 entreprise programmeurs, les gens qui écrivent de la documentation ont tendance à utiliser des mots comme "ne devrait pas" et "ne jamais" pour dire "ne fais pas cela, sauf si vous savez vraiment ce que vous faites et pourquoi".
Un couple de mes autres favoris dans le C# monde sont ce qu'ils vous disent de "ne jamais appeler de verrouillage(ce)" ou "ne jamais appeler GC.Collect()". Ces deux sont de force déclaré dans beaucoup de blogs et de documentation officielle, et de l'OMI qui sont complètes de la désinformation. À un certain niveau, cette désinformation sert son but, en ce qu'il garde les débutants loin de faire des choses qu'ils ne comprennent pas avant de l'avoir pleinement des recherches sur les alternatives, mais en même temps, il est difficile de trouver des informations via les moteurs de recherche qui semblent tous pointer vers des articles de vous dire de ne pas faire quelque chose tout en n'offrant pas de réponse à la question "pourquoi pas?"
Politiquement, il se résume à ce que les gens considèrent le "good design" ou "mauvais design". La documentation officielle ne doit pas dicter le design de mon application. Si il y a vraiment une raison technique que vous ne devriez pas appel à sleep(), puis de l'OMI, la documentation doit indiquer qu'il est totalement d'accord pour l'appeler en vertu des scénarios spécifiques, mais peut-être offrir des alternatives des solutions scénario indépendant ou plus approprié pour les autres scénarios.
Clairement appelant "sleep()" est utile dans de nombreuses situations, lorsque les délais sont clairement définis dans le monde réel-temps, toutefois, il existe des systèmes plus sophistiqués pour l'attente et de signalisation des threads qui doit être pris en compte et compris avant de commencer à jeter un sleep() dans votre code, et en jetant inutile de sommeil() relevés dans votre code est généralement considéré comme l'un des débutants tactique.
C'est le 1).la filature et 2).boucle d'interrogation de vos exemples que les gens en garde contre, pas le Fil.Sleep() de la partie.
Je pense que le Thread.Sleep() est généralement ajoutés pour améliorer facilement le code qui tourne ou dans un bureau de vote de la boucle, c'est juste associé avec les "mauvais" du code.
En plus, les gens faire des trucs comme:
où la variable inWait n'est pas accessible dans un thread-safe, ce qui provoque également des problèmes.
Ce que les programmeurs veulent voir, c'est le fils contrôlé par des Événements et de Signalisation et Verrouillage des constructions, et quand vous faites cela, vous n'aurez pas besoin de Thread.Sleep(), et les préoccupations au sujet de thread-safe variable d'accès sont également éliminées. Comme un exemple, vous pourriez créer un gestionnaire d'événement associé à la classe FileSystemWatcher et utiliser un événement pour déclencher votre 2ème exemple au lieu de boucle?
Andreas N. mentionné, lire Filetage en C#, par Joe Albahari, il est vraiment vraiment bon.
Thread.Sleep()
avec une autre fonction, et l'appeler dans la boucle while?Sommeil est utilisé dans les cas où indépendant de programme(s) que vous n'avez aucun contrôle sur peut parfois utiliser couramment utilisée pour la ressource (par exemple, un fichier), que les besoins du programme d'accès lorsqu'il s'exécute, et lorsque la ressource est en cours d'utilisation par ces autres programmes de votre programme est bloqué de l'utiliser. Dans ce cas, où vous avez accès à la ressource dans votre code, vous mettez votre accès à la ressource dans un try-catch (pour intercepter l'exception lorsque vous ne pouvez pas accéder à la ressource), et vous le mettez dans une boucle while. Si la ressource est libre, le sommeil n'est jamais appelé. Mais si la ressource est bloqué, alors vous dormez pour une quantité appropriée de temps, et de la tentative d'accès à la ressource (ce pourquoi vous êtes en boucle). Cependant, gardez à l'esprit que vous devez mettre une sorte de limiteur sur la boucle, de sorte qu'il n'est pas potentiellement une boucle infinie. Vous pouvez configurer votre condition limite à N le nombre de tentatives (c'est ce que j'utilise habituellement), ou vérifier l'horloge système, d'ajouter un montant fixe de temps pour obtenir une limite de temps, et arrêter d'essayer d'accès si vous atteignez la limite de temps.
Je suis d'accord avec beaucoup ici, mais je pense aussi que ça dépend.
Récemment, j'ai fait ce code:
C'était une simple animation de la fonction, et j'ai utilisé
Thread.Sleep
sur elle.Ma conclusion, si il fait le boulot, l'utiliser.
DoEvents
, et est indicateur d'une mauvaise conception ...Pour ceux d'entre vous qui n'a pas vu un seul argument valable contre l'utilisation de Fil.Dormir dans le SCÉNARIO 2, il y a vraiment une demande de sortie de la boucle while
(SCÉNARIO 1/3 est tout simplement stupide donc pas digne de plus de mentionner)
Beaucoup de ceux qui prétendent être dans-le-savoir, en hurlant Fil.Le sommeil est le mal a omis de mentionné une seule raison valable pour ceux d'entre nous qui ont exigé une raison pratique de ne pas l'utiliser, mais c'est tout, merci à Pete - Fil.Le sommeil est Mal (peut être facilement évitée avec un timer/gestionnaire)
Thread.Sleep
n'est pas la raison (le nouveau fil un la continue, tandis que la boucle est)! vous pouvez seulement de supprimer lesThread.Sleep
-ligne - et le tour est joué: le programme ne se termine pas ainsi...