2009-02-24 11 views
0

Une application C++ existante avec des problèmes de fuites de mémoire parfois notoires doit être appelée à partir d'une application Windows basée sur un serveur .Net. Les temps de collecte des ordures .Net ne sont pas déterminables et parfois l'objet C++ est détruit ou n'est pas détruit "à temps" produisant des résultats imprévisibles et s'écrasant généralement l'application web C#. Quelle est la meilleure façon de pousser les objets C++ sur la pile de récupération de place aussi souvent que possible, mais pas si souvent que de supprimer la référence .Net à l'objet COM. Gardez à l'esprit que les objets COM peuvent générer des sous-objets afin que le nombre de références .Net des objets COM puisse changer avec seulement un appel de fonction et pas nécessairement une instanciation. Au fur et à mesure que les fuites de mémoire se produisent et que les objets COM ne sont pas nettoyés, les performances se dégradent jusqu'à ce qu'il soit si lent que IIS se déclenche plusieurs fois sur lui-même, puis tombe en panne. Redémarrer IIS résout le problème jusqu'à la prochaine fois. Les redémarrages périodiques sont utiles, mais une journée chargée peut en être la cause pendant le jour ouvrable.Comment gérer les objets COM dans une application Web .Net

J'ai dû résoudre cela en utilisant .Net 1.1 il y a quelques années. Je me demandais si quelqu'un d'autre avait ma solution ou un meilleur. Ce n'est pas ASP.NET. C'est une DLL .Net.

Le résultat final n'était pas complètement satisfaisant et le serveur web se bloque tous les quelques mois.

+0

J'ai tendance à être d'accord que c'est difficile ou impossible avec .Net 1.1, mais nous avons la possibilité de passer à .Net 2.0. Est-ce que c'est intrinsèquement meilleur ou y a-t-il de nouvelles fonctions qui pourraient aider? – ssorrrell

Répondre

1

Vous demandez "Quelle est la meilleure façon de pousser les objets C++ sur la pile de garbage collection aussi souvent que possible", mais les objets C++ ne sont jamais récupérés. Peut-être regardez-le de cette façon ...

Vous avez un processus qui instancie un tas d'objets C++. Certains de ces objets C++ implémentent des objets COM, et leur durée de vie est donc gérée via AddRef/Release. Certains de ces objets COM sont importés dans le monde .NET et sont enveloppés avec un RCW (wrapper appelable à l'exécution). Seul le RCW est un objet .NET et va dans le tas collecté par le garbage.

Sans aucune intervention de votre part, le RCW sera finalement GC'd et quand cela se produit, il fera une version contre son objet COM sous-jacent. Si vous voulez libérer l'objet COM immédiatement, sans attendre GC, vous pouvez appeler ...

System.Runtime.InteropServices.Marshal.ReleaseComObject

... ou même FinalReleaseComObject si vous êtes sûr qu'il est ce que tu veux.

Pour en revenir à votre question: vous voulez savoir comment supprimer les objets C++ sans libérer la référence .NET à votre objet COM. Puisque les objets C++ n'existent pas dans le tas .NET, il n'y a aucun moyen d'y parvenir directement. Vous pouvez exposer une méthode à partir de votre objet COM qui supprime tous ses objets C++ et l'appeler simplement à partir de votre code .NET. Mais je suppose que s'il était possible pour votre objet COM d'identifier tous les objets C++ qui fuyaient, vous le feriez déjà. J'espère que j'ai expliqué pourquoi il n'y a aucun moyen de réaliser ce que vous suggérez dans votre question, mais il existe de nombreux outils pour vous aider à trouver et réparer vos fuites de mémoire. Je suggère d'utiliser un outil tel que LeakDiag (recherche StackOverflow pour cela) pour savoir où votre code C++ fuit la mémoire.

La solution pragmatique, si vous utilisez IIS6 ou une version ultérieure, consiste à configurer le recyclage du pool d'applications. Vous pouvez modifier les chiffres de manière à ce que les processus soient supprimés et redémarrés avant qu'ils ne fassent jamais suffisamment de place dans la mémoire, et cela fonctionne normalement de telle sorte que les utilisateurs ne remarquent aucun temps d'arrêt.

0

Créez une application COM + et placez les classes COM que vous utilisez dans cette application. De cette façon, tous les objets COM sont instanciés dans un processus séparé.Vous pouvez périodiquement libérer tous les objets COM et simplement redémarrer le processus d'application COM +.

+0

Garder les objets COM dans un processus séparé est une idée intéressante. Je ne suis pas sûr que ce soit possible. – ssorrrell

+0

Voilà comment fonctionne COM +. Vous prenez votre serveur COM in-process et demandez à COM + de créer une "application COM +" qui est en réalité un serveur COM + non traité avec les mêmes fonctionnalités. Et hors processus signifie que tous les objets sont dans un processus séparé. – sharptooth

Questions connexes