Pour des performances optimales avec des unités exécutées simultanément, écrivez votre propre pool de threads, où un pool d'objets Thread est créé au démarrage et passe au blocage (anciennement suspendu), en attendant un contexte à exécuter (un objet avec une interface standard implémentée par votre code).
Tant d'articles sur Tâches vs Threads vs .NET ThreadPool ne vous donnent pas vraiment ce dont vous avez besoin pour prendre une décision en matière de performances. Mais quand vous les comparez, les Threads l'emportent et surtout un pool de Threads. Ils sont les meilleurs répartis sur les processeurs et démarrent plus rapidement.
Ce qui devrait être discuté est le fait que l'unité d'exécution principale de Windows (y compris Windows 10) est un thread et que la surcharge de changement de contexte du système d'exploitation est généralement négligeable. En termes simples, je n'ai pas été en mesure de trouver des preuves convaincantes de bon nombre de ces articles, que l'article revendique de meilleures performances en économisant le changement de contexte ou une meilleure utilisation du processeur.
Maintenant, pour un peu de réalisme:
La plupart d'entre nous n'auront pas besoin que notre application soit déterministe, et la plupart d'entre nous n'ont pas une expérience difficile avec les threads, ce qui, par exemple, vient souvent avec le développement d'un système d'exploitation. Ce que j'ai écrit ci-dessus n'est pas pour un débutant.
Le plus important est donc de discuter de ce qui est facile à programmer.
Si vous créez votre propre pool de threads, vous aurez un peu d'écriture à faire car vous devrez vous préoccuper du suivi de l'état d'exécution, comment simuler la suspension et la reprise, et comment annuler l'exécution - y compris dans une application à l'échelle fermer. Vous devrez peut-être également vous demander si vous souhaitez développer dynamiquement votre pool et quelle sera la limitation de capacité de votre pool. Je peux écrire un tel cadre en une heure, mais c'est parce que je l'ai fait tant de fois.
Le moyen le plus simple d'écrire une unité d'exécution est peut-être d'utiliser une tâche. La beauté d'une tâche est que vous pouvez en créer une et la lancer en ligne dans votre code (bien que la prudence puisse être justifiée). Vous pouvez transmettre un jeton d'annulation à gérer lorsque vous souhaitez annuler la tâche. En outre, il utilise l'approche de promesse pour chaîner les événements et vous pouvez lui faire renvoyer un type de valeur spécifique. De plus, avec async et await, plus d'options existent et votre code sera plus portable.
En substance, il est important de comprendre les avantages et les inconvénients de Tasks vs Threads vs .NET ThreadPool. Si j'ai besoin de hautes performances, je vais utiliser des threads et je préfère utiliser mon propre pool.
Un moyen simple de comparer est de démarrer 512 threads, 512 tâches et 512 threads ThreadPool. Vous trouverez un retard au début avec les threads (d'où pourquoi écrire un pool de threads), mais les 512 threads s'exécuteront dans quelques secondes tandis que les threads Tasks et .NET ThreadPool prennent jusqu'à quelques minutes pour démarrer.
Voici les résultats d'un tel test (i5 quad core avec 16 Go de RAM), donnant toutes les 30 secondes pour fonctionner. Le code exécuté effectue des E / S de fichier simples sur un lecteur SSD.
Résultats de test