C # – ThreadPool vs tâches

Comme certains l’ont peut-être vu dans .NET 4.0, ils ont ajouté un nouvel espace de noms System.Threading.Tasks ce qui est essentiellement ce que sont des moyens, une tâche. Je ne l’utilise que depuis quelques jours, en utilisant ThreadPool.

Lequel est plus efficace et moins consommateur de ressources? (Ou simplement mieux dans l’ensemble?)

L’objective de l’espace de noms Tasks est de fournir une architecture enfichable pour rendre les applications multitâches plus faciles à écrire et plus flexibles.

L’implémentation utilise un object TaskScheduler pour contrôler la gestion des tâches. Cela a des méthodes virtuelles que vous pouvez remplacer pour créer votre propre gestion des tâches. Les méthodes incluent par exemple

 protected virtual void QueueTask(Task task) public virtual int MaximumConcurrencyLevel 

L’utilisation de l’implémentation par défaut entraînera une surcharge minime, car il existe une enveloppe autour de l’implémentation des threads .NET, mais je ne m’attendrais pas à ce qu’elle soit énorme.

Il existe une implémentation (brouillon) d’un TaskScheduler personnalisé qui implémente plusieurs tâches sur un seul thread ici .

lequel est le plus efficace et le moins consommateur de ressources?

Peu importe, il y aura très peu de différence.

(Ou simplement mieux dans l’ensemble)

La classe de tâches sera plus facile à utiliser car elle offre une interface très propre pour le démarrage et la jointure des threads, et transfère les exceptions. Il prend également en charge une forme (limitée) d’équilibrage de charge.

“A partir de .NET Framework 4, la TPL est la méthode préférée pour écrire du code multithread et parallèle.”

http://msdn.microsoft.com/en-us/library/dd460717.aspx

La planification est un aspect important des tâches parallèles.

Contrairement aux threads, les nouvelles tâches ne commencent pas nécessairement à s’exécuter immédiatement. Au lieu de cela, ils sont placés dans une queue de travail. Les tâches s’exécutent lorsque leur planificateur de tâches associé les supprime de la queue, généralement lorsque les cœurs sont disponibles. Le planificateur de tâches tente d’optimiser le débit global en contrôlant le degré de simultanéité du système. Tant qu’il y a suffisamment de tâches et que les tâches sont suffisamment dépourvues de dépendances de sérialisation, les performances du programme sont adaptées au nombre de cœurs disponibles. De cette manière, les tâches incarnent le concept de parallélisme potentiel

Comme je l’ai vu sur msdn http://msdn.microsoft.com/en-us/library/ff963549.aspx

Un autre point intéressant à prendre en compte est que lorsque vous utilisez ThreadPool, vous n’avez aucun moyen d’abandonner ou d’attendre les threads en cours d’exécution (sauf si vous le faites manuellement dans la méthode du thread), mais l’ utilisation de task est possible . Corrigez-moi si j’ai tort, s’il-vous plait

Fil

La chose nue, vous n’avez probablement pas besoin de l’utiliser, vous pouvez probablement utiliser une tâche LongRunning et bénéficier de ses installations.

les tâches

Abstraction au-dessus des fils. Il utilise le pool de threads (sauf si vous spécifiez la tâche comme une opération LongRunning , si tel est le cas, un nouveau thread est créé sous le capot pour vous).

Pool de threads

Comme son nom l’indique: un pool de threads. Le framework .NET gère-t-il un nombre limité de threads? Pourquoi? Parce que l’ouverture de 100 threads pour exécuter des opérations coûteuses sur le processeur avec seulement 8 cœurs n’est certainement pas une bonne idée. Le framework va maintenir ce pool pour vous, réutiliser les threads (ne pas les créer / tuer à chaque opération), et exécuter certains d’entre eux en parallèle de manière à ce que votre CPU ne soit pas brûlé.

OK, mais quand utiliser chacun?

En résumé: utilisez toujours des tâches.

La tâche est une abstratcion, donc c’est beaucoup plus facile à utiliser. Je vous conseille de toujours essayer d’utiliser Tasks et si vous rencontrez un problème qui vous oblige à manipuler un thread par vous-même (probablement 1% du temps), utilisez des threads.

MAIS être conscient que:

  • I / O Bound : Pour les opérations liées aux E / S (appels de firebase database, fichiers lecture / écriture, appels d’API, etc.), n’utilisez jamais de tâches normales , utilisez des tâches ou des threads LongRunning si nécessaire, mais pas des tâches normales. Parce que cela vous mènerait à un pool de threads avec quelques threads occupés et beaucoup d’autres tâches en attente de son tour pour prendre le pool.
  • CPU Bound : Pour les opérations liées au CPU, utilisez simplement les tâches normales et soyez heureux.