J'ai défini le thread max à 10. J'ai ensuite ajouté la tâche 22000 à l'aide de ThreadPool.QueueUserWorkItem. Il est très probable que toutes les tâches 22000 n'ont pas été terminées après l'exécution du programme. Y at-il une limite combien de tâche peut être mise en file d'attente pour les threads disponibles?Nombre maximal d'éléments mis en file d'attente dans ThreadPool.QueueUserWorkItem
Répondre
La file d'attente n'a aucune limite pratique, mais le pool lui-même ne dépassera pas 64 descripteurs d'attente, c'est-à-dire que le nombre total de threads est actif.
De l'documentation of ThreadPool:
Note: Les fils dans le pool de threads gérés sont des fils de fond. Autrement dit, leurs propriétés IsBackground sont vraies. Cela signifie qu'un thread ThreadPool ne gardera pas une application en cours d'exécution après que tous les threads de premier plan se soient terminés.
Est-il possible que vous vous éteigniez avant que toutes les tâches aient été traitées?
Il s'agit d'une question liée à la mise en œuvre et l'implémentation de cette fonction a changé un peu avec le temps. Mais dans .Net 4.0, vous êtes essentiellement limité par la quantité de mémoire dans le système car les tâches sont stockées dans une file d'attente en mémoire. Vous pouvez le voir en explorant l'implémentation dans le réflecteur.
Si vous devez attendre que toutes les tâches soient traitées, vous devez les gérer vous-même. Les threads ThreadPool sont tous des threads d'arrière-plan et ne conservent pas l'application en vie.
Ceci est une façon relativement propre pour gérer ce type de situation:
using (var mre = new ManualResetEvent(false))
{
int remainingToProcess = workItems.Count(); // Assuming workItems is a collection of "tasks"
foreach(var item in workItems)
{
// Delegate closure (in C# 4 and earlier) below will
// capture a reference to 'item', resulting in
// the incorrect item sent to ProcessTask each iteration. Use a local copy
// of the 'item' variable instead.
// C# 5/VS2012 will not require the local here.
var localItem = item;
ThreadPool.QueueUserWorkItem(delegate
{
// Replace this with your "work"
ProcessTask(localItem);
// This will (safely) decrement the remaining count, and allow the main thread to continue when we're done
if (Interlocked.Decrement(ref remainingToProcess) == 0)
mre.Set();
});
}
mre.WaitOne();
}
Cela étant dit, il est généralement préférable de « groupe » ensemble vos éléments de travail si vous avez des milliers d'entre eux, et ne les traite pas comme des éléments de travail distincts pour le pool de threads. Il y a quelques frais généraux impliqués dans la gestion de la liste des éléments, et puisque vous ne serez pas capable de traiter 22000 à la fois, vous feriez mieux de les regrouper en blocs. Avoir des éléments de travail uniques chaque processus 50 ou plus sera probablement aider votre débit global un peu ...
Bonne idée, mais l'application attendait tous les threads. Le regroupement est également une très bonne suggestion. –
Un bug a causé mon problème, mais fondamentalement la réponse à la question est la suivante. –
Merci @keith. Il semble donc que la seule limite réelle à la taille de la file d'attente est la taille d'un objet File d'attente générique (ou similaire). – matrixugly
Quoi? J'ai 150 threads de pool de threads actifs! – Vlad