2009-01-05 7 views
1

J'ai une petite application qui recherche et stocke les noms d'un grand nombre de fichiers au démarrage. Je divise cette recherche en plusieurs objets Thread qui recherchent chacun un répertoire et ramènent les résultats au thread principal.C# thread commence à partir du débogueur, mais ne démarre pas autonome

Lorsque les charges d'application, je passe par chaque fil et le charger:

foreach(Thread t in m_threads) 
{ 
    t.Start(); 
    while(!t.IsAlive){} 
} 

Quand je commence cette application dans le débogueur, il charge et les fils trouvent rapidement tous les fichiers. Cependant, si je commence en dehors du débogueur, il se fige. Attacher le débogueur au processus, je peux voir que IsAlive ne retourne jamais vrai.

Je suis novice en threading C#, donc est-ce que quelqu'un a une idée de ce qui ne va pas, ou comment je peux plus facilement déboguer ce qui se passe?

Répondre

2

Il n'est peut-être pas exactement lié à la raison pour laquelle les choses gèlent, mais votre implémentation est assez discutable. Vous énumérer sur une collection de threads, commencez chacun, mais ensuite bloquer jusqu'à ce que le fil est fini? Je pense que ce que vous vouliez faire est de démarrer tous les threads, puis de bloquer jusqu'à ce que tous les threads soient terminés. (Note: Ceci suppose que vous vouliez écrire:. « while (t.IsAlive) {} », car en attendant le fil de commencer est encore moins logique)

En ce qui concerne le gel, nous devrons peut-être voir le reste du code. Puisque vous avez dit que vous êtes novice en threading C#, et en regardant ce que vous avez fait ci-dessus, je suppose que vous êtes également novice en matière de threading, ce qui signifie qu'il peut y avoir plusieurs endroits où un problème peut survenir.

1

Vous voulez peut-être dire IsAlive() "never returns false". Eh bien, si oui, c'est parce que vos threads continuent à s'exécuter à l'infini. Peut être la méthode que vous appelez dans ces threads a une boucle infinie ou quelque chose.

3

Le thread peut avoir terminé le traitement avant votre vérification par IsAlive.

Pourquoi attendez-vous en vérifiant le drapeau IsAlive quand même? Pourquoi ne pas lancer tous les threads à la place, puis dans une autre boucle, appeler le Join() pour attendre que les threads se terminent? Pas besoin de vérifier "IsAlive".

Encore mieux, pourquoi ne pas utiliser le ThreadPool au lieu d'utiliser une pile de threads?

+0

Merci, je vais regarder dans ThreadPools. – tenpn

1

Il semble que j'ai mal compris le code que j'ai coupé et collé pour créer mon code d'enfilage. J'ai supposé que la ligne while (! T.isAlive) {} bloquait jusqu'à ce que le thread puisse démarrer correctement, et pensait que c'était une administration nécessaire. J'ai supprimé cette ligne et l'application se lance en dehors du débogueur. Je rejoins les threads plus tard dans le code, donc ça devrait l'être.

Y a-t-il un "NEWB!" marque? :)

0

Je ne sais pas ce que vous faites dans vos fils exactement, mais je pense que ...

multithreading + application se comporte différemment avec débogueur attaché = conditions de course

Je suis assez sûr que vous avez des problèmes de synchronisation.

1

Avec le code que vous avez fourni ci-dessus, Il me semble que vous voulez démarrer les threads de manière séquentielle. Si oui, pourquoi avez-vous besoin de beaucoup de threads? 1 thread peut faire le travail.

EDIT: (après votre réponse)

Ok. Je vois que vous avez supprimé la ligne discutable.

Néanmoins, dans votre cas, je considérerais utiliser un seul thread pour charger ces noms de fichiers car vous n'accédez qu'à une ressource d'E/S (le disque). Chaque thread est en compétition pour cette ressource. Avez-vous essayé de déplacer 1 gros fichier dans Windows et ensuite déplacer un autre gros fichier pendant que le premier est encore en mouvement? Les performances de votre disque diminuent. Pour cette raison, je ne créerais qu'un seul thread pour chaque ressource d'E/S différente.

1

Je vous recommande de ne pas contenir une collection de Threads, mais plutôt d'utiliser Threadstarts. Si vous les rejoignez plus tard, il n'est pas nécessaire d'attendre que le Thread soit en cours d'exécution, donc while-loop n'est pas nécessaire. Assurez-vous que vos Threads sont marqués comme Background-Threads, afin qu'ils soient nettoyés automatiquement après l'exécution.

Je ferais ceci comme ceci: Liste threadStarters = new List();

foreach (ThreadStart ts in threadStarters) 
{ 
    Thread t = new Thread(ts); 
    t.IsBackground = true; 
    t.Start(); 
} 
Questions connexes