148 votes

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);
    }
}

176voto

Andreas Niedermair Points 8907

Le problème avec l'appel Thread.Sleep sont expliquées tout à fait brièvement ici:

Thread.Sleep a son utilisation: simulation des opérations de longue durée alors que les tests de débogage sur un thread MTA. Dans .NET il n'y a aucune autre raison de l'utiliser.

Thread.Sleep(n) moyen de bloquer le thread en cours pour au moins le nombre de timeslices (ou thread quantums) qui peuvent se produire au sein d' n millisecondes. La longueur d'un timeslice est différent sur différentes versions/types de Windows et les différents processeurs et varie généralement de 15 à 30 millisecondes. Cela signifie que le fil est presque garanti à bloc pour plus de n millisecondes. La probabilité que votre thread re-réveiller exactement après l' n millisecondes est à peu près aussi impossible que impossible, peut être. Donc, Thread.Sleep est inutile pour le chronométrage.

Les Threads sont une ressource limitée, ils prennent environ 200 000 cycles pour créer et environ 100 000 cycles pour les détruire. Par défaut, ils réserve de 1 méga-octet de mémoire virtuelle pour sa pile et l'utilisation de 2 000 à 8 000 cycles pour chaque changement de contexte. Ce qui rend l'un thread en attente d'un énorme de déchets.

La solution préférée: WaitHandles

Les plus-erreur à l'aide de Thread.Sleep avec un temps de construire (démo et de répondre, blog de nice-entrée)

EDIT:
Je voudrais améliorer ma réponse:

Nous avons 2 différents cas d'utilisation: 1) Nous sommes en attente parce que nous savons un spécifique de temps, alors que nous devrions continuer (utiliser Thread.Sleep, System.Threading.Timer ou similaires) 2) Nous sommes en attente en raison des changements de condition de quelques temps ... mot-clé(s) est/sont un certain temps! si l'état-vérifier dans notre code de domaine, nous devrait utiliser WaitHandles - sinon le composant externe doit fournir une certaine forme de crochets ... si ce n'est pas sa conception, c'est mal! Mon réponse couvre principalement les cas d'utilisation de 2

38voto

Swab.Jat Points 209

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 quand 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 appelle?).

Donc si en+Thread.Des travaux de sommeil, pourquoi compliquer les choses? Seule la syntaxe de juristes, d'être pratique!

-8voto

Swab.Jat Points 209

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 le Mal (peut être facilement évitée avec un timer/gestionnaire)

    static void Main(string[] args)
    {
        Thread t = new Thread(new ThreadStart(ThreadFunc));
        t.Start();

        Console.WriteLine("Hit any key to exit.");
        Console.ReadLine();

        Console.WriteLine("App exiting");
        return;
    }

    static void ThreadFunc()
    {
        int i=0;
        try
        {
            while (true)
            {
                Console.WriteLine(Thread.CurrentThread.ThreadState.ToString() + " " + i);

                Thread.Sleep(1000 * 10);
                i++;
            }
        }
        finally
        {
            Console.WriteLine("Exiting while loop");
        }
        return;
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X