2009-03-18 6 views
0

Je commence presque 5 threads dans un programme en C# .NET. Mais parfois certains de ces threads s'arrêtent ou deviennent inexplicables même avant la fin de l'exécution de la fonction qui leur est assignée.Comment empêcher les threads de mourir ou simplement de quitter C# .NET?

Cela arrive de manière aléatoire. Si j'essaie de déboguer le code en mettant des points d'arrêt - Cela fonctionne bien.

Et parfois tous les threads exécutent parfaitement les fonctions assignées. Ils ne partagent aucune ressource entre eux.

  Thread[] td = new Thread[5]; 
      for (count = 4; count >= 0; --count) 
      { 
       ds[count] = dba.getData(ru[count]); 
       td[count] = new Thread(delegate() { runRule[count].performTask(ru[count], ds[count], count); }); 
       td[count].Name = "Thread " + count.ToString(); 
       td[count].Start(); 
       Thread.Sleep(50); 
      } 

Si je supprime la dernière ligne « Thread.Sleep (50) » seul le premier fil fixaient fonctionne et reste d'entre eux meurent juste. Est-ce que quelqu'un peut expliquer pourquoi les fils meurent?

Répondre

4

Je pense qu'ils ne deviennent morts - je soupçonne que le problème est que vous n'êtes pas en cours d'exécution en fait les règles que vous pensez que vous êtes. Lorsque vous utilisez les variables locales d'une méthode dans une méthode anonyme, les variables elles-mêmes sont capturées. Dans ce cas, vous capturez la variable locale count, puis vous la modifiez (au fur et à mesure que le compteur de boucles diminue). Au moment où un thread créé lorsque compte = 4 commence à courir, count peut être 3 - donc il va appeler runRule[3].performTask(ru[3], ds[3], 3). En fait, count pourrait changer tandis que les expressions sont en cours d'évaluation ce qui pourrait causer beaucoup de plaisir.

Le moyen de contourner cela est d'avoir une variable "locale" différente pour chaque itération de la boucle. Il est facile à faire:

Thread[] td = new Thread[5]; 
for (count = 4; count >= 0; --count) 
{ 
    int copy = count; 
    ds[count] = dba.getData(ru[count]); 
    td[count] = new Thread(delegate() { 
     runRule[copy].performTask(ru[copy], ds[copy], copy); 
    }); 
    td[count].Name = "Thread " + count.ToString(); 
    td[count].Start(); 
    Thread.Sleep(50); 
} 

Maintenant, les seules variables capturées dans le délégué sont copy et runRule/ru/ds - Je suppose que les trois derniers ne changent pas. Une nouvelle "instance" de la variable copy est créée à chaque fois que vous faites le tour de la boucle, de sorte que les modifications n'interfèrent pas les unes avec les autres.

Voir si cela aide - c'est au moins une cause potentielle de confusion massive, et pourrait bien être le problème.

+0

ThankyouForUrReplyLe problème évoqué est évité Thread.Sleep (50) .Cause lorsque le thread principal attend 50 millisecs, les threads sont créés avant la prochaine itération.Ce n'est pas le problème principal ici, j'ai 5 prgresbrs pour montrer combien de progrès est fait .Les threads quittent juste après avoir montré quelques progrès – LoyalBanana

1

Si un thread atteint la fin de son chemin d'exécution, il se terminera automatiquement. Dans votre exmaple une fois que le thread a terminé quelle que soit la méthode performTask, il va quitter. Si vous voulez qu'un thread reste indéfiniment (à des fins de débogage uniquement car vous ne voulez pas que les threads inutilisés traînent dans une application réelle), vous pouvez ajouter quelque chose comme le suivant à la fin de la méthode que le thread est fonctionnement.

ManualResetEvent stayAlive = new ManualResetEvent(false); 
stayAlive.WaitOne(); 
+0

Merci pour votre réponse, je ne veux pas que les threads traînent pour toujours, le problème ici est qu'ils ne terminent pas leur chemin d'exécution complet. Ils meurent ou quittent juste avant d'exécuter tout le code. – LoyalBanana

Questions connexes