6
votes

Comment obtenir un deuxième système.thread.threadpool?

Si j'utilise le threadpool de manière imbriquée, mon application est suspendue:

 ThreadPool.QueueUserWorkItem((state) =>
      ThreadPool.QueueUserWorkItem(Action));


6 commentaires

Pourquoi imbriquez-vous une piscine de fil?


Cela ne devrait pas causer à pendre votre programme. Vous avez probablement un autre problème.


A la façon dont cette question est appelée «impasse de filetage». Il s'agit d'un danger inhérent au pool de thread .NET et est décrit au chapitre 'Deadlock' dans Cet article .


... Et aussi dans Cet article .


Un "problème" avec le fil-piscine par défaut / singleton est-il n'autorisant pas les allocations de threads pour différents composants d'un programme - les MintHreads / Maxthreads sont globales. Pour un programme avec de nombreux threads (ou encore plus simplement, pour de nombreuses tâches) pour différents composants avec des caractéristiques distinctes dans un processus, il ne permet tout simplement pas la configuration nécessaire. Bien que, sans doute, cela indique qu'il pourrait y avoir trop dans un processus, cela ne fixe pas la limitation.


La plupart des problèmes liés à la threadpool que j'ai rencontrés ont été liés à une croissance non liée des choses ( Tâches Tâches Coux ) qui tentent d'utiliser le fil-piscine. Le contrôle de la concurrence maximale (malheureusement manquant de tâches, disponible dans la plupart des TPL) est très important pour la stabilité globale du programme: accordé, il y a toujours le cas d'une molette morte si "nécessitant un autre fil que peut être créé" qui est vraiment un programme problème de conception.


6 Réponses :


0
votes

Il y a un et un seul threadpool.


2 commentaires

Eh bien, techniquement, il y en a un par processus (ou un par appdomain, je ne suis pas sûr), alors vous pourrait obtenir des multiples impliqués. Cela semble juste comme une très mauvaise idée. :)


Vrai. Cette mise en œuvre particulière semblait être confinée à un seul processus.



4
votes

Votre application est probablement suspendue car vous le remplissez jusqu'au point où tous les threads actifs attendent des threads en file d'attente. (Je suppose que le thread d'origine attend le (s) élément (s) de travail que les files d'attente complètent.)

Le threadpool a par défaut 25 * (Nombre de CPU) Threads Workers (IIRC).

Vous voulez probablement retravailler votre façon de faire la queue. Si vous les festez des file d'attente, puis de la finition et de la sortie du fil, vous allez bien, mais que vous avez des objets de travail suspendus à attendre d'autres processus, c'est généralement une mauvaise conception; Si c'est ce que vous faites, vous devez probablement utiliser de vrais threads ou un design complètement différent. Utiliser des threads réels est probablement une idée tout aussi mauvaise, car tout ce qui va faire (sur la base de ce que je peux surmonter de votre utilisation), vous créerez un grand nombre de discussions, ce qui ne fera rien de bon pour votre performance.

Un meilleur design pourrait être d'avoir une sorte de file d'attente ou de pile que quelques-uns (2-4 en fonction du nombre de processeurs) Les threads ouvriers ajoutent des éléments et des éléments pop sur les éléments de travail. Si un élément doit faire la queue un nouvel élément, il suffit de l'ajouter à la pile (et s'ajoute à la pile avec une sorte de suivi de dépendance si elle doit attendre l'autre élément).


10 commentaires

Il serait intéressant d'obtenir un nombre définitif de threads par threadpool. Je l'ai vu quelque part, je ne peux tout simplement pas me rappeler où. Quoi qu'il en soit, je créerais un nouveau threadpool plutôt que d'essayer de manifester le threadpool dans une file d'attente - il suffit de garder une collection de threadpools instanciés (tableau, liste, dict).


@dbboarman Vous pouvez réellement définir la taille de threadpool à l'aide des méthodes statiques sur ThreadPool


Je suis d'accord. Vous devriez regarder vos threads de votre travailleur pour voir s'il y a des objets partagés pouvant causer une impasse et revisiter votre architecture pour réaligner vos "frontières".


@dbboarman Je ne suggère pas "Manhirling". S'il a obtenu des tâches qui doivent exécuter d'autres tâches récursives, une pile ou une file d'attente (en fonction de la sémantique d'exécution) est probablement le moyen le plus propre de la gérer. Autoriser une explosion de thread (threads Créer des threads Créer des threads) va simplement causer des problèmes de performance, qu'il s'agisse d'une threadpool ou d'un système System.threading.threads.


@Technophile: Désolé, je n'étais pas clair - mon commentaire a été dirigé vers l'OP sur Manholdling. Il semble que ce soit la nidification serait le pire type de coercition.


@ROB: Je sais que vous pouvez augmenter la taille de la threadpool - honnêtement, je me demandais pourquoi l'OP ne fait pas simplement cela. Si un nouveau threadpool est le seul moyen d'obtenir une mise en œuvre résolue, alors soyez-le.


L'augmentation de la taille de la threadpool est plus susceptible de retarder le problème (généralement légèrement) que de résoudre le problème, de mon expérience.


@dboRarman @technophile Je suis avec Technophile. Il doit y avoir un moyen de faire cela qui n'est pas une impasse-personne à la place


Roger Roger, première fois, ne nierait pas Nurshpools ... Si .NET 4.0 n'est pas une option (ce qui est tout à fait probable), l'OP devrait commencer avec seulement une poignée (dis 5) threads. Si plus sont nécessaires, tournez à une utilité pour dire un maximum de 10. L'OP peut toujours utiliser le threadpool.QueueUserWorkItem lorsque l'un des threads est devenu ralenti. Est-ce que ça sonne bien?


Je voudrais probablement faire tourner le nombre de threads de Workitem 2xcpus et ne les quitte jamais, puis utilisez une ou plusieurs files d'attente / piles pour gérer leur charge de travail. Cela suppose que la charge de travail est assez stable; S'il s'agit d'une situation où le besoin de tâches de base est rare ou imprévisible, vous pourriez le faire différemment. OTOH, si c'est le but majeur de l'application, je pourrais envisager d'utiliser quelque chose comme Windows Workflow Foundation.



7
votes

Il n'y a qu'un seul threadpool - ce n'est pas quelque chose que vous pouvez (ou devrait) faire plus d'une instance de dans une application.

Je ne recommande pas de faire cela, mais si vous le souhaitez vraiment, vous pouvez utiliser plusieurs instances de votre propre implémentation threadpool, telle que smartthreadpool . Ce serait, techniquement, permettrait de séparer les "piscines de fil".

Cependant, je soupçonne que vous êtes suspecté à cause d'un Imporlock , non dû au threadpool usage. J'éditionnerais où vous obtenez les suspensions. Le Visualizer Concurrence VS2010 est très agréable pour cela, si vous avez une copie de la version bêta VS 2010 installée.


2 commentaires

Choisi à cause du deuxième paragraphe


"Ce n'est pas quelque chose que vous pouvez (ou devrait) faire plus d'une instance dans une application." Bollucks! Je fais tout le temps dans le monde de Java. Il est très courant d'avoir une piscine de fil par module système ou tâche. L'intégration de printemps est-ce par exemple pour ses polleurs et adaptateurs via un exécuteur exécutif.



2
votes

Vous utilisez les mauvais outils.

in .NET 4.0 Ils ont introduit la bibliothèque parallèle de la tâche. Cela vous permet de faire des choses comme utilisez plusieurs piscines THEAD, ainsi que des relations parent-enfant entre les éléments de travail.

Démarrer avec la classe de tâches, qui remplace ThreadPool.QueueUserSerWorkItem.

http: // msdn.microsoft.com/en-us/library/system.threading.Tasks.Task(vs.100).aspx

Modifier

Exemple de création de votre propre piscine de thread à l'aide de tâches et de tâchesCHEDuler.

http://msdn.microsoft.com/ EN-US / Bibliothèque / DD997413 (vs.100) .aspx


5 commentaires

Ce n'est pas techniquement correct. Le TPL est construit sur le .NET ThreadPool - il ne crée pas plusieurs piscines de fil, mais utilise plutôt le threadpool (amélioré) dans le cadre de planification des tâches.


La tâche TaskSchDuler dans la tâche.Start (TaskScheduler) est abstraite, vous pouvez donc construire vos piscines de fil de toute façon que vous voulez.


Le choix du cadre ou des outils est l'OP de faire, et le bref code de code indiqué ne fournit pas suffisamment de contexte pour que nous jugeons si l'utilisation de threadpool directement, ou indirectement via la TPL, est appropriée ou non.


Il peut choisir n'importe quel outil qu'il souhaite, mais au mieux de mes capacités, je vais suggérer le bon outil.


Enfin, j'ai vérifié, Threadpool a été réécrit de rester assis sur TPL plutôt que l'inverse. C'est parce que TPL propose d'autres avantages tels que des files d'attente de vol de travail.



1
votes

tandis que le API Windows Permet à plusieurs piscines de thread dans un processus , .NET ne les directement l'expose. Dans la structure .NET ..

il y a exactement un fichier threadpool par .NET AppDomain , et absolument aucun moyen de changer cela.

Ainsi, avec différents domaines d'application. Il est possible d'avoir différents .NET ThreadPools dans le même processus.

(Remarque: les heuristiques de l'algorithme de montée de la colline utilisée dans .NET sont également déterminées sur une base de threadpool Per-.net. Ceci, le long sans être capable de spécifier un nombre maximum de travailleurs par Type, est un inconvénient d'un "global par AppDomain" threadpool avec des charges de travail variées.)


0 commentaires

-1
votes

Un moyen utilise le blocageCollection. C'est la classe que je construise pour cela:

mis à jour à 2018-04-23: xxx

pour le voir fonctionner dans la construction de ce test d'unité : xxx

Vous pouvez désormais avoir autant de sondages que vous le souhaitez, simplement en créant de nouveaux objets de persil.

Notez que Le code n'est pas complètement testé.


0 commentaires