82 votes

Pourquoi ajoutant à TextBox.Text pendant une boucle prend plus de mémoire à chaque itération ?

Petite Question

J'ai une boucle qui s'exécute 180 000 fois. À la fin de chaque itération, il est censé ajouter les résultats d'une zone de texte, qui est mis à jour en temps réel.

À l'aide de MyTextBox.Text += someValue est à l'origine de la demande de manger d'énormes quantités de mémoire, et il est à court de mémoire disponible après quelques milliers d'enregistrements.

Est-il un moyen plus efficace de l'ajout de texte à un TextBox.Text 180 000 fois?

Edit j'ai vraiment ne se soucient pas le résultat de ce cas particulier, cependant, je veux savoir pourquoi ce qui semble être un dévoreur de mémoire, et si il ya un moyen plus efficace pour ajouter du texte à une zone de texte


Long (D'Origine) Question

J'ai une petite application qui lit une liste de numéros d'ID dans un fichier CSV et génère un rapport au format PDF pour chacun. Après chaque fichier pdf est généré, l' ResultsTextBox.Text est ajoutée avec le Numéro d'identification du rapport qui les a transformés et qu'il a été traité avec succès. Le processus s'exécute sur un thread d'arrière-plan, de sorte que le ResultsTextBox est mis à jour en temps réel, les éléments traités

Je suis actuellement en cours d'exécution de l'application à l'encontre de 180 000 numéros d'identification, cependant la mémoire de l'application est de prendre croît de façon exponentielle à mesure que le temps passe. Il commence par environ 90K, mais par environ 3000 dossiers c'est de prendre environ 250 MO et par 4000 enregistrements de l'application est de prendre environ 500 MO de mémoire.

Si je commenter la mise à jour des Résultats de la zone de texte, la mémoire reste relativement stationnaire à environ 90K, donc je peux supposer que la rédaction ResultsText.Text += someValue est ce qui est à l'origine de consommer de la mémoire.

Ma question est, pourquoi est-ce? Quelle est la meilleure façon d'ajout de données à une zone de texte.Texte qui ne mange pas de mémoire?

Mon code ressemble à ceci:

try
{
    report.SetParameterValue("Id", id);

    report.ExportToDisk(ExportFormatType.PortableDocFormat,
        string.Format(@"{0}\{1}.pdf", new object[] { outputLocation, id}));

    // ResultsText.Text += string.Format("Exported {0}\r\n", id);
}
catch (Exception ex)
{
    ErrorsText.Text += string.Format("Failed to export {0}: {1}\r\n", 
        new object[] { id, ex.Message });
}

Il convient également de mentionner que l'application est une chose une seule fois et il n'a pas d'importance que va prendre quelques heures (ou jours :)) pour générer tous les rapports. Ma principale préoccupation est que si elle frappe le système de limite de mémoire, il s'arrête en cours d'exécution.

Je suis très bien avec la sortie de la ligne de mise à jour des Résultats de zone de texte commenté pour exécuter cette chose, mais je voudrais savoir si il y a une mémoire plus efficace d'ajouter des données à un TextBox.Text pour les projets futurs.

119voto

keyboardP Points 44625

Je soupçonne que la raison pour laquelle que l’utilisation de la mémoire est si grande est parce que les zones de texte maintient une pile afin que l’utilisateur peut annuler/rétablir texte. Cette fonctionnalité ne semble pas nécessaire dans votre cas, essayez donc de définir `` sur false.

14voto

Cypher2100 Points 246

Utilisation au lieu de . Il est facile de rater car c’est sur la zone de texte, pas TextBox.Text. Comme StringBuilder, ceci évitera de créer des copies de l’ensemble du texte chaque fois que vous ajoutez quelque chose.

Il serait intéressant de voir comment cela se compare à la `` indicateur de réponse de keyboardP.

9voto

Darthg8r Points 2722

Ne pas ajouter directement à la propriété text. Utiliser StringBuilder pour l’ajout, alors quand, définissez le .text sur la chaîne finie de stringbuilder

5voto

ChaosPandion Points 37025

Au lieu d’utiliser une zone de texte, je ferais ce qui suit :

  1. Ouvrir un fichier texte et diffuser les erreurs dans un fichier journal au cas où.
  2. Utilisez un contrôle de zone de liste pour représenter les erreurs à éviter la copie des chaînes potentiellement massives.

4voto

jwiscarson Points 2152

Personnellement, j'ai toujours utiliser string.Concat* . Je me souviens avoir lu une question sur un Débordement de Pile d'années qu'il avait de profilage statistique comparant les méthodes courantes, et (semble) pour rappeler qu' string.Concat qui a gagné.

Néanmoins, le mieux que je puisse trouver est cette question de référence et ce String.Format vs StringBuilder question, qui mentionne qu' String.Format utilise un StringBuilder en interne. Cela me fait me demander si votre mémoire de porcs se situe ailleurs.

*sur la base de James commentaire, je tiens à préciser que je ne fais jamais lourde chaîne de formatage, comme je me concentre sur web-basé de développement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X