Question

J'écris une application qui devra utiliser Timers, mais potentiellement un très grand nombre d'entre eux.Dans quelle mesure le System.Threading.Timer classe?La documentation dit simplement qu'il est "léger", mais n'explique pas davantage.Ces minuteries sont-elles aspirées dans un seul thread (ou un très petit pool de threads) qui traite tous les rappels au nom d'un Timer, ou est-ce que chacun Timer a son propre fil de discussion ?

Je suppose qu'une autre façon de reformuler la question est la suivante :Comment est System.Threading.Timer mis en œuvre?

Était-ce utile?

La solution

Je dis cela en réponse à beaucoup de questions :N'oubliez pas que le code source (géré) du framework est disponible.Vous pouvez utiliser cet outil pour tout obtenir : http://www.codeplex.com/NetMassDownloader

Malheureusement, dans ce cas précis, une grande partie de l'implémentation est en code natif, vous ne pouvez donc pas la regarder...

Cependant, ils utilisent certainement des threads de pool plutôt qu'un thread par minuterie.

La manière standard d'implémenter une grande collection de timers (c'est ainsi que le noyau le fait en interne, et je suppose que c'est indirectement la façon dont se termine votre grande collection de timers) est de maintenir la liste triée par durée jusqu'à l'expiration - de sorte que le le système n'a qu'à se soucier de vérifier la prochaine minuterie qui va expirer, pas la liste entière.

En gros, cela donne O(log n) pour démarrer un minuteur et O(1) pour traiter les minuteurs en cours d'exécution.

Modifier:Je viens de regarder dans le livre de Jeff Richter.Il dit (de Threading.Timer) qu'il utilise un seul thread pour tous les objets Timer, ce thread sait quand le prochain timer (c'est-à-direcomme ci-dessus) est dû et appelle ThreadPool.QueueUserWorkItem pour les rappels, le cas échéant.Cela a pour effet que si vous ne terminez pas le traitement d'un rappel sur une minuterie avant l'échéance du suivant, votre rappel réapparaîtra sur un autre thread de pool.Donc, en résumé, je doute que vous voyiez un gros problème avec le fait d'avoir beaucoup de minuteurs, mais vous pourriez souffrir d'un épuisement du pool de threads si un grand nombre d'entre eux se déclenchent en même temps et/ou si leurs rappels s'exécutent lentement.

Autres conseils

Je pense que vous voudrez peut-être repenser votre conception (c'est-à-dire si vous contrôlez vous-même la conception).Si vous utilisez tellement de minuteries que cela vous préoccupe, il existe clairement un potentiel de consolidation.

Voici un bon article de MSDN Magazine d'il y a quelques années qui compare les trois classes de timer disponibles et donne un aperçu de leurs implémentations :

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

Consolidez-les.Créez un service de minuterie et demandez-le pour les minuteries.Il n'aura que conserver 1 minuterie active (pour le prochain appel d'échéance) ...

Pour que cela constitue une amélioration par rapport à la simple création de nombreux objets Threading.Timer, vous devez supposer que ce n'est pas exactement ce que Threading.Timer fait déjà en interne.Je serais intéressé de savoir comment vous êtes arrivé à cette conclusion (je n'ai pas démonté les éléments natifs du framework, vous pourriez donc avoir raison).

^^ comme le dit DannySmurf :Consolidez-les.Créez un service de minuterie et demandez-le pour les minuteries.Il lui suffira de conserver 1 minuterie active (pour le prochain appel dû) et un historique de toutes les demandes de minuterie et de recalculer cela sur AddTimer() / RemoveTimer().

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top