Question

De temps en temps, je reçois une System.Threading.ThreadStateException lorsque j'essaie de redémarrer un thread.Le code en question est le suivant :

// Make sure the thread is done stopping
while (this.mThread.ThreadState == ThreadState.Running)
{ 
    Thread.Sleep(0);
}
// Respawn a thread if the current one is stopped or doesn't exist
if (this.mThread == null || this.mThread.ThreadState == ThreadState.Stopped)
{ 
    this.mThread = new Thread(new ParameterizedThreadStart(Monitor)); }
// Start the thread
if (check)
{ 
    this.mThread.Start(60000); 
}
else
{   
    this.mThread.Start(0); 
}

Donc deux questions : est-ce la bonne façon de faire les choses, et c'est le cas, existe-t-il un moyen d'éviter que l'erreur ne se produise ?

Était-ce utile?

La solution

Le problème est que vous avez du code qui vérifie d'abord s'il doit créer un nouvel objet thread, et un autre morceau de code qui détermine s'il faut démarrer l'objet thread.En raison de conditions de concurrence critique et de choses similaires, votre code peut finir par essayer d'appeler .Start sur un objet thread existant.Étant donné que vous ne publiez pas les détails derrière le vérifier variable, il est impossible de savoir ce qui pourrait déclencher ce comportement.

Vous devez réorganiser votre code afin que .Start soit garanti d'être appelé uniquement sur de nouveaux objets.En bref, vous devez placer la méthode Start dans la même instruction if que celle qui crée un nouvel objet thread.

Personnellement, j'essaierais de réorganiser l'intégralité du code afin de ne pas avoir besoin de créer un autre thread, mais d'envelopper le code à l'intérieur de l'objet thread dans une boucle afin que le thread continue.

Autres conseils

Il est possible qu'un thread se trouve dans plusieurs états à la fois. La propriété ThreadState est donc en fait un bitmap des états possibles.Ainsi, tester l’égalité avec un seul État ne vous donnera pas le bon résultat.Vous devrez faire quelque chose comme :

if((mThread.ThreadState & ThreadState.Running) != 0)

Cependant, vérifier l’état du thread n’est pas une bonne chose.Je ne comprends pas tout à fait ce que vous essayez de réaliser, mais je suppose que vous attendez la fin d'un thread avant de le redémarrer.Dans ce cas il faut faire :

mThread.Join();
mThread = new Thread(new ParameterizedThreadStart(Monitor));
if(check)
    mThread.Start(60000);
else
    mThread.Start(0);

Bien que si vous décrivez le problème que vous essayez de résoudre plus en détail, je suis presque certain qu'il y aura une meilleure solution.Attendre la fin d'un fil juste pour le redémarrer ne me semble pas très efficace.Peut-être avez-vous simplement besoin d’une sorte de communication inter-thread ?

John.

Une ThreadStateException est levée car vous essayez de démarrer un thread qui n'est pas dans un état démarrable.Les situations les plus probables seraient qu'il soit déjà en cours d'exécution ou qu'il soit complètement fermé.

Il y a potentiellement plusieurs choses qui pourraient se produire.Premièrement, le thread est peut-être passé de Running à StopRequested, qui n'est pas encore complètement arrêté, donc votre logique ne crée pas de nouveau thread et vous essayez de démarrer un thread qui vient de terminer son exécution ou est sur le point de le faire. terminer l'exécution (aucun des deux n'est un état valide pour le redémarrage).

L'autre possibilité est que le thread ait été abandonné.Les threads qui sont abandonnés passent à l'état Aborted, pas à l'état Stopped, et bien sûr ne sont pas non plus valides pour le redémarrage.

En réalité, le seul type de fil de discussion encore actif qui peut être « redémarré » est celui qui est suspendu.Vous souhaiterez peut-être utiliser ce conditionnel à la place :

if (this.mThread == null || this.mThread.ThreadState != ThreadState.Suspended)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top