2009-05-12 8 views
7

Wir haben eine große Speicherleckanalyse durchgeführt und festgestellt, dass einer der beitragenden Faktoren die Entfernung von Delegaten bei Ereignissen war Objekte werden nicht schnell genug (oder manchmal für immer) gelöscht.Irgendwelche Ideen zum Schreiben einer statischen Analyse-Regel (FXCop), um sicherzustellen, dass Ereignisdelegaten entfernt werden

Hätte jemand Ideen, wie man eine Regel in FXCop schreibt, um sicherzustellen, dass Delegierte aus den Handlern entfernt werden?

Ich habe gerade gesehen this und als solche werde ich dort für weitere Informationen fragen.

Antwort

2

Ok, neben dem Problem der die tatsächliche Kontrolle der Umsetzung (meiner Meinung nach ist dies sehr ähnlich zu einem path coverage und damit nicht praktikabel) - hier ist der Weg, eine neue FxCop Regel, es zu schreiben:

Zuerst einige Artikel, die mir einmal geholfen:

Die Implementierung einer einfachen Regel ist keine große Sache. In Ihrem Projekt benötigen Sie eine Rules.xml-Datei als eingebettete Ressource (siehe here).Sie leiten Ihre Klasse von BaseIntrospectionRule und Ihren Code Check add() - Methode:

public override ProblemCollection Check(TypeNode typeNode) 
{ 
    if(type.IsPublic) 
    { 
    Problems.Add(new Problem(...)); 
    } 
    return Problems; 
} 

ich dies vor einiger Zeit tat. Ich hoffe es funktioniert immer noch wie beschrieben :)

+0

danke das ist am nächsten zu der Antwort, die ich gesucht habe. Aber in Fairness sind auch die anderen Antworten wahr, und wir implementieren, wo immer möglich, schwache Referenzen. –

0

Ist es sicher anzunehmen, dass die Objekte, die die Handler implementieren, irgendwie Referenzen auf das Objekt mit den Ereignissen haben? Wenn das der Fall ist, ist es besser, herauszufinden, wie man den Zyklus auf andere Weise durchbricht.

Wir hatten etwas Ähnliches mit Ereignishandlern auf ASP.NET-Seiten. Die Objekte, die die Handler implementierten, hatten auch Verweise auf die Seiten. Nachdem wir so viele Links architektonisch wie möglich durchbrochen hatten, wurden die wenigen Überbleibsel in WeakReferences geändert. Keine Speicherprobleme mehr!

+0

Interessant ... danke. –

3

Sie müssen genauer sein. Sie müssen nicht überprüfen, ob ALLE Ereignisdelegierten abgemeldet wurden, da ein Abonnent in einem häufigen Fall ein kürzeres Leben hat als ein Publisher. Und ein Speicherverlust tritt nur dann auf, wenn Ihr Abonnent länger lebt als ein Publisher. Daher gibt es eine Referenz, die GC daran hindert, das Publisher-Objekt zu sammeln.

Jetzt müssen wir sicherstellen, dass Sie sich abmelden, wenn Sie ein Ereignis auf einem relativ kurzlebigen Objekt abonnieren.

Eine Heuristik, die ich in diesem Fall entwickeln kann: analysieren Sie alle Objekte mit lokaler Variablen (die durch den aktuellen Codeblock {} definiert sind) und alle Objekte, die Sie explizit disposieren. Notieren Sie für jedes Ereignis auf diesen Objekten die Anzahl der Abonnements und die Anzahl der Abmeldungen. Wenn die erste Zahl größer ist, geben Sie eine Warnung ab.

Natürlich deckt das nicht alle Fälle ab, aber ich denke, dass kein statischer Ansatz alle Fälle in diesem Problem abdecken kann, Sie brauchen eine Methode, die gut genug ist.

Ich werde hier nicht die Vorteile der dynamischen Analyse und Code-Reviews erwähnen, da es sich um ein separates Thema handelt, das nicht mit der Frage zusammenhängt.

+0

Danke. Ich schätze die detaillierte Antwort. Ich bin ziemlich sicher auf die Dinge, die ich überprüfen möchte. Was ich herausfinden möchte, sind Informationen darüber, wie man das in einer FX-Regel macht. Ich finde keine anständigen Informationen darüber, wie man mit den FX-Assemblies neue komplexe Regeln schreiben kann. –

1

Können Sie eine Regel erzwingen, dass alle Event Subscriptions durch WeakReferences behandelt werden sollen? Ich denke, dies sollte einfacher zu implementieren sein, als den tatsächlichen Ablauf Ihres Programms zu analysieren.