2010-12-16 165 views
0

J'ai créé un pool de threads qui ont 5 threads. Les deux démarreront lorsque mon application démarrera. Le problème est que je crée autant d'objets en fonction d'appel boucle de fil en arrière sur chacun des fils, et la mémoire est augmentation par seconde lorsque l'application courante, ceci est appel en boucle du fil de retour de la fonction:
Dois-je appeler GC.Collect dans le pool de threads personnalisé?

ThreadLoop vide

() {
      while (true) {
                  var checkItems = _workItems.Where (w => w.ActivedTime> 3) .ToList();
                  foreach (var i in checkItems) {
                        _workItems [i.Id] .ActivedTime = 0;
                        _workItems [i.Id] .ExecutePostBack();
                 }
                  // Recréer nouveau _workItems dictionnaire de
                _workItems = _workItems.Where (w => w .ActivedTime > 0) .ToDictionary();
                // fil de sommeil pour libérer momory
                Thread.Sleep (1000);
                // Appel Grab collecteur de mémoire libre
                GC.Collecte();
     }}

Je suis confus que, appelle GC.Collect() sur chaque fils comme ce bon ou mauvais? Dose-elle cause de mauvaises performances?

Répondre

0

Il est déconseillé d'appeler GC.Collect à moins que vous n'en ayez vraiment besoin, comme dans certains cas de coin avec COM interop. Au mieux, vous invoquez le GC plus qu'il ne le faut, au pire, vous pourriez promouvoir des objets d'une autre durée de vie dans des générations plus élevées du GC, ce qui les rendrait plus coûteux à nettoyer plus tard.

Le CPG est déclenché lors de la pression de la mémoire lorsque la mémoire est allouée, et non dans le temps. Il n'est donc pas rare de voir un pic de mémoire temporaire qui traîne longtemps si vous n'allouez plus de nouveaux objets. Dans ce cas, il peut être correct d'appeler GC.Collect mais j'éviterais de l'appeler en boucle si vous le pouvez.

+0

Je dois poster le même commentaire pour vous, les gars. Je veux aussi entendre votre opinion: "quand j'ajoute GC.Collect(), la mémoire est d'environ 100 mb lorsque je lance un pool de threads avec 1000 éléments de travail sur chaque thread, pendant 2 heures, mais quand je supprime GC.Collect() (Laisser .Net recueillir pour moi) la mémoire en hausse seconde par seconde et rarement vers le bas, il est environ 300 ~ 400 mb quels éléments de travail même pendant 2 heures.Le collecteur de saisie .Net fonctionne-t-il pire? Comment faire. mon cas ?" – UmbalaAZ

0

Vous n'avez pas besoin d'appeler GC.Collect() dans la plupart des cas, sauf dans de rares cas (et je pense que ce n'est pas le cas). Voir ici pour plus d'explications: http://blogs.msdn.com/b/ricom/archive/2004/11/29/271829.aspx

+0

Merci pour votre conseil. Mais lorsque j'ajoute GC.Collect(), la mémoire est d'environ 100 mb lorsque je lance un pool de threads avec 1000 éléments de travail sur chaque thread, pendant 2 heures. mais quand j'enlève GC.Collect() (Laisser .Net collecter pour moi) la mémoire en hausse seconde par seconde et rarement en bas, c'est environ 300 ~ 400 mb qui fonctionnent même éléments pendant 2 heures. Est-ce que le collecteur de grab .Net fonctionne plus mal? Comment faire .net collecteur grab fonctionne mieux dans mon cas? – UmbalaAZ

+0

Si vos tests de performance montrent le contraire, faites ce que vous croyez le mieux. La VM .NET est censée se régler et fonctionner mieux à long terme - c'est la théorie de toute façon. – muratgu

+0

Uhm, je suis d'accord, je vais choisir la solution après le test et la mesure. – UmbalaAZ

1

Si vous devez vous demander d'appeler GC.Collect, la réponse est presque définitivement "non". Le GC est conçu pour fonctionner automatiquement selon les besoins, et l'invoquer soi-même dit "Je sais mieux que le GC lui-même quand il devrait fonctionner". Toute personne qui ne connaît pas les détails de GC est plus susceptible d'avoir tort que de bien, et va réellement faire empirer les choses.

Le meilleur plan d'action consiste presque toujours à laisser le GC prendre soin de lui-même.

+0

Merci pour votre conseil. Mais lorsque j'ajoute GC.Collect(), la mémoire est d'environ 100 mb lorsque je lance un pool de threads avec 1000 éléments de travail sur chaque thread, pendant 2 heures. mais quand j'enlève GC.Collect() (Laisser .Net collecter pour moi) la mémoire en hausse seconde par seconde et rarement en bas, c'est environ 300 ~ 400 mb qui fonctionnent même éléments pendant 2 heures. Est-ce que le collecteur de grab .Net fonctionne plus mal? Comment faire .net collecteur grab fonctionne mieux dans mon cas? – UmbalaAZ

+0

GC s'exécute quand c'est nécessaire, c'est-à-dire lorsque la mémoire est faible. Si vous avez beaucoup de mémoire, il est possible que GC ne fonctionne pas jusqu'à la fermeture de l'application, voire pas du tout. L'application semblera utiliser régulièrement plus de mémoire. Cela ne veut pas dire que ça tourne "pire" - juste qu'il y a un tas de choses qui n'ont pas encore besoin de collection. – cHao

+0

Il est impossible d'attendre la fermeture de l'application pour libérer de la mémoire. Comment puis-je envoyer au GC des objets mortels gratuits et faire fonctionner le GC plus tôt et en toute sécurité sans le forcer à collecter immédiatement? – UmbalaAZ