J'ai écrit un programme qui utilise tous les cœurs disponibles en utilisant Parallel.ForEach
. La liste pour le ForEach
contient ~ 1000 objets et le calcul pour chaque objet prend un certain temps (~ 10 sec). Dans cette configuration scénario I d'une minuterie comme ceci:System.Timers.Timer massivement inexact
timer = new System.Timers.Timer();
timer.Elapsed += TimerHandler;
timer.Interval = 15000;
timer.Enabled = true;
private void TimerHandler(object source, ElapsedEventArgs e)
{
Console.WriteLine(DateTime.Now + ": Timer fired");
}
Au moment où la méthode TimerHandler
est un bout pour vous assurer que le problème ne soit pas causé par cette méthode.
Mon attente est que la méthode TimerHandler
sera exécutée toutes les 15 secondes ~. Cependant, le temps entre deux appels à cette méthode atteint même 40 secondes, soit 25 secondes de trop. En utilisant new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount -1 }
pour la méthode Parallel.ForEach
cela ne se produit pas et l'intervalle attendu de 15 secondes est vu.
Est-il prévu que je dois m'assurer qu'il y a toujours un noyau disponible par minuteur actif? Semble être un peu plus bizarre, car le "réservé" pourrait être une ressource précieuse pour mon calcul.
Edit: Comme indiqué par Yuval la fixation d'un minimum fixé de fils dans la piscine par ThreadPool.SetMinThreads
résolu le problème. J'ai également essayé new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }
(donc sans le -1
dans la question initiale) pour la méthode Parallel.ForEach
et cela résout également le problème. Cependant, je n'ai aucune bonne explication pourquoi ces modifications ont résolu le problème. Peut-être qu'il y avait tellement de threads créés que le thread de la minuterie a été "perdu" pendant un temps "long" jusqu'à ce qu'il soit à nouveau exécuté.
Si vous définissez explicitement le nombre de threads dans le pool de threads avant d'exécuter la boucle parallèle, est-ce toujours le cas? (En utilisant 'ThreadPool.SetMinThreads') –
utilisez-vous le processeur lorsque vous utilisez tous les processeurs? Si c'est le cas, tous les événements répondront plus lentement en raison de la façon dont Windows traite le message. – Jeremy
Je soupçonne que le thread exécutant les threads parallèles (qui est probablement le même thread exécutant le timer) se bloque lui-même. Si vous pouvez trouver un moyen d'exécuter votre minuterie sur un thread différent, votre problème peut disparaître. Le thread qui exécute votre minuteur peut être différent en fonction de la manière dont votre application est hébergée (par exemple Windows Forms vs console) –