J'ai essayé d'apprendre la programmation multithread en C# et je ne sais pas quand il est préférable d'utiliser le pool de threads ou de créer mes propres threads. Un livre recommande d'utiliser le pool de threads uniquement pour les petites tâches (quoi que cela veuille dire), mais je n'arrive pas à trouver de véritables directives. Quelles sont les considérations que vous utilisez pour prendre cette décision de programmation ?
Réponses
Trop de publicités?Si vous avez beaucoup de tâches logiques qui nécessitent un traitement constant et que vous voulez que cela soit fait en parallèle, utilisez le pool+scheduler.
Si vous avez besoin d'effectuer simultanément des tâches liées aux entrées-sorties, comme le téléchargement de données à partir de serveurs distants ou l'accès aux disques, mais que vous devez le faire toutes les quelques minutes, créez vos propres threads et tuez-les une fois que vous avez terminé.
Edit : A propos de certaines considérations, j'utilise des pools de threads pour l'accès aux bases de données, la physique/simulation, l'IA (jeux), et pour des tâches scriptées exécutées sur des machines virtuelles qui traitent beaucoup de tâches définies par l'utilisateur.
Normalement, un pool se compose de 2 threads par processeur (donc probablement 4 aujourd'hui), mais vous pouvez configurer le nombre de threads que vous voulez, si vous savez combien vous en avez besoin.
Edit : La raison de faire vos propres threads est à cause des changements de contexte, (c'est quand les threads ont besoin d'échanger dans et hors du processus, avec leur mémoire). Avoir des changements de contexte inutiles, disons lorsque vous n'utilisez pas vos threads, en les laissant simplement s'asseoir comme on pourrait le dire, peut facilement réduire de moitié les performances de votre programme (disons que vous avez 3 threads dormants et 2 threads actifs). Ainsi, si ces threads de téléchargement sont juste en train d'attendre, ils consomment des tonnes de CPU et refroidissent le cache pour votre application réelle.
Je vous suggère d'utiliser un pool de threads en C# pour les mêmes raisons que dans tout autre langage.
Lorsque vous souhaitez limiter le nombre de threads en cours d'exécution ou que vous ne voulez pas supporter la charge de leur création et de leur destruction, utilisez un pool de threads.
Par petites tâches, le livre que vous lisez entend des tâches dont la durée de vie est courte. S'il faut dix secondes pour créer un thread qui ne fonctionne qu'une seconde, c'est un endroit où vous devriez utiliser des pools (ignorez mes chiffres réels, c'est le ratio qui compte).
Sinon, vous passez la majeure partie de votre temps à créer et à détruire des fils plutôt que de faire simplement le travail pour lequel ils sont prévus.
Voici un bon résumé du pool de threads dans .Net : http://blogs.msdn.com/pedram/archive/2007/08/05/dedicated-thread-or-a-threadpool-thread.aspx
L'article indique également dans quels cas il est préférable de ne pas utiliser le pool de fils et de créer son propre fil de discussion.
Je recommande vivement la lecture de ce livre électronique gratuit : Threading en C# par Joseph Albahari
Au moins lisez la section "Getting Started". Ce livre électronique constitue une excellente introduction et contient également de nombreuses informations sur l'enfilage avancé.
Savoir s'il faut ou non utiliser le pool de fils n'est qu'un début. Ensuite, vous devrez déterminer quelle méthode d'entrée dans le pool de fils répond le mieux à vos besoins :
- Bibliothèque parallèle de tâches (.NET Framework 4.0)
- ThreadPool.QueueUserWorkItem
- Délégués asynchrones
- Travailleur d'arrière-plan
Cet e-book les explique tous et conseille de les utiliser ou de créer son propre fil.
Le pool de threads est conçu pour réduire le changement de contexte entre vos threads. Considérez un processus dans lequel plusieurs composants sont en cours d'exécution. Chacun de ces composants pourrait créer des threads de travail. Plus il y a de threads dans votre processus, plus vous perdez de temps à changer de contexte.
Maintenant, si chacun de ces composants mettait en file d'attente des éléments dans le pool de threads, vous auriez beaucoup moins de surcharge liée au changement de contexte.
Le pool de threads est conçu pour maximiser le travail effectué sur vos processeurs (ou cœurs de processeur). C'est pourquoi, par défaut, le pool de threads fait tourner plusieurs threads par processeur.
Dans certaines situations, il est préférable de ne pas utiliser le pool de threads. Si vous attendez une entrée/sortie ou un événement, etc., vous bloquez le thread du pool et il ne peut être utilisé par personne d'autre. La même idée s'applique aux tâches de longue durée, bien que ce qui constitue une tâche de longue durée soit subjectif.
Pax Diablo soulève également un bon point. La création de fils n'est pas gratuite. Cela prend du temps et ils consomment de la mémoire supplémentaire pour leur espace de pile. Le pool de threads réutilisera les threads pour amortir ce coût.
Remarque : vous avez posé une question sur l'utilisation d'un thread de pool de threads pour télécharger des données ou effectuer des E/S de disque. Vous ne devriez pas utiliser un thread de pool pour cela (pour les raisons que j'ai décrites ci-dessus). Utilisez plutôt les E/S asynchrones (c'est-à-dire les méthodes BeginXX et EndXX). Pour un FileStream
qui serait BeginRead
et EndRead
. Pour un HttpWebRequest
qui serait BeginGetResponse
et EndGetResponse
. Ils sont plus compliqués à utiliser, mais c'est la bonne façon d'effectuer des E/S multithreads.
- Réponses précédentes
- Plus de réponses