Fuite de mémoire dans .NETCF - Création de contrôles dynamiques?
-
03-07-2019 - |
Question
J'ai un problème de fuite de mémoire dans une application .NET CF.
Utilisation de RPM , j'ai identifié cette création dynamique. les contrôles ne sont pas récupérés comme prévu. Exécuter le même morceau de code dans .NET Window Forms se comporte différemment et dispose le contrôle comme prévu.
Afficher le résultat de RPM via PerfMon pour le compteur Process Heap :
GC Heap:
Ma meilleure hypothèse est que la référence faible au groupe d'experts est, pour une raison inconnue, ne rend pas l'objet éligible au GC, n'est-ce pas?
Remarque: même si Dispose () résout le problème lié à l'échantillon, je ne parviens pas facilement à l'intégrer à l'application existante, car elle n'est pas aussi nette. pour déterminer quand l'objet n'est plus utilisé.
J'ai inclus une version simplifiée du code source pour illustrer le problème:
using System;
using System.Windows.Forms;
namespace CFMemTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Calling this event handler multiple times causes the memory leak
private void Button1_Click(object sender, EventArgs e)
{
Panel uc = new Panel();
// Calling uc.Dispose() cleans up the object
}
}
}
Mise à jour:
1. L'appel de GC.Collect () n'entraîne pas non plus le nettoyage des panneaux.
2. Utilisation de .NET CF 2.0 SP1 sur un périphérique Windows CE 4.2.
La solution
Certaines informations supplémentaires expliquant ce comportement ici.
Tout ce qui est lié à l'interface utilisateur sur NETCF est intentionnellement retiré de la portée du GC afin il n'est jamais collecté . Ce comportement est différent du bureau et a été changé dans NETCF V3.5 (à moins d’exécuter en mode de compatibilité).
C'est tellement différent parce que l'interface utilisateur gérée les classes sur NETCF sont complètement différent du bureau. Ils sont minces wrappers sur l'implémentation native qui était nécessaire pour atteindre acceptable performances.
Je ne suis pas sûr qu’une telle ressource existe. Mais en réalité, tout ce que vous devez savoir, c'est: il n’est jamais collecté, il faut appeler disposer. Tu devrais réellement faire ça sur le bureau aussi, mais si vous ne le faites pas sa façon plus pardonner. Pas bientôt NETCF.
Autres conseils
Un formulaire ne supprime pas automatiquement tous les contrôles créés dans son code car il n'a aucun moyen de savoir qu'il existe. Pour que le formulaire soit automatiquement éliminé une fois éliminé, vous devez l'ajouter à la collection Controls.
Maintenant, dans votre cas, cela ne peut rien faire. Je ne peux pas dire si votre exemple est artificiel ou réel. Si le problème est réel, le comportement est attendu, car le Panel ne sera pas collecté lorsque la variable sortira de sa portée (elle ne sera pas sûre non plus sur le bureau). Il devient disponible pour la collecte, mais cela signifie simplement que lors du prochain passage de collection, il sera balayé. À moins que vous ne provoquiez un GC, il ne sera pas libéré. ??
Je vous recommande vivement de jeter un coup d'œil à Webcast MSDN sur la gestion de la mémoire dans les FC . Il fournit une explication beaucoup plus détaillée de ce qui se passe sous le capot - bien plus que ce que nous pourrions fournir dans une réponse ici.
Êtes-vous sûr d'avoir une fuite de mémoire? Le ramasse-miettes .NET Compact Framework fonctionne légèrement différemment de celui du framework .NET complet. Sur le blog de Steven Pratschner :
Une collection est lancée lorsque:
1 Mo d'objets ont été alloués,
Une application est déplacée en arrière-plan,
Une erreur d'allocation de mémoire se produit
Une application appelle GC.Collect.
Je pense que vous devez également supprimer dynamiquement le gestionnaire de clic sur un bouton, comme vous pouvez le constater sur ce blog: http://blogs.msdn.com/stevenpr/archive/2007/03/08/finding-managed-memory-leaks-using-the-net-cf-remote-performance-monitor.aspx
Il vient aussi de Steven Pratschner.
À propos, la diffusion Web mentionnée ci-dessus est liée ici: http://msevents.microsoft.com/cui/ WebCastEventDetails.aspx? Culture = fr-US & ampID EventID = 1032318791 & CountryCode = US
J'espère que ça aide!