PropertyChange events und Garbage Collection



  • Das GUI Objekt ist kein Standard GUI Objekt. Also kein Textfield oder Ähnliches. ISt glaube ich auch relativ egal. Die frage ist doch viel mehr ob das

    new PropertyChangedEventHandler(....);
    

    Weak-refs verwendet. MyClass ist selbst keine GUI Klasse und implementiert nur
    INotifyPropertyChanged.



  • Wenn du per Code, das Event anmeldest, wird es nicht automatisch abgemeldet wenn dein Control verschwindet. Du arbeitest ja sicherlich mit WPF oder? Normaler Weiße sollte man die PropertyChanged Events nicht per Code an die Controls anmelden, sondern eigentlich macht das die WPF alleine, um Änderungen direkt an das Control zu publizieren. Dementsprechenden werden die Events beim löschen auch wieder abgemeldet.



  • Ich arbeite nicht mit WPF. Es ist auch keine GUI im klassischen Sinne gemeint. Sondern eher ein neues STeuerelement welches is implementiere. Ich zeichne eigene Objekte in dieses Steuerelement etc. Ich denke also das ich mich dafür um das Eventhandling alleine Kümmern muss.



  • Uhi ok das ist natürlich anstrengend. Wenn du also ein Steuerelement selbst implementierst, könntest du, oder hast du sicherlich schon, für diese Element die IDisposable Schnittstelle implementieren und beim Disposen Entfernst du einfach alle angemeldeten Handler. Aber das ist Spekulation ob das geht, was du eventuell erstmal Testen solltest, ob nach dem Löschen des Steuerlements immernoch angemeldete Events aktiv sind.



  • Das mit IDisposable für die Elemente hatte ich mir auch schon überlegt. Dann muss ich aber eh Dispose beim Entfernen der Elemente aufrufen. Damit wäre das Dispose zumindest nur eine zentrale Stelle, an der ich die ganze Abmelderei erledigen könnte. Zumindest vereinfache ich mir damit einiges. Mal schauen wie ich das hinkriege.
    Welche Möglichkeit hätte ich herauszufinden ob noch irgendwelche Eventhandler aktiv sind? Mit den Debugger auf das Event schauen ist nur bedingt hilfreich. Da sehe ich nur wenn gar kein Handler mehr angemeldet ist, da dies dann null sein sollte. Ich kann aber nirgendwie sehen welche Handler angemeldet sind, oder?



  • Naja nicht wirklich.Was du machen könntest, wäre das selber mitzuloggen, welche Handler sich angemeldet haben, vielleicht hilft das ja was:

    public class Test : INotifyPropertyChanged
        {
            private static List<PropertyChangedEventHandler> Handler = new List<PropertyChangedEventHandler>();
    
            private event PropertyChangedEventHandler _propertyChanged;
            public event PropertyChangedEventHandler PropertyChanged
            {
                add
                {
                    this._propertyChanged += value;
                    Handler.Add(value);
                }
                remove
                {
                    this._propertyChanged -= value;
                    if (Handler.Contains(value))
                        Handler.Remove(value);
                }
    
            }
    
        }
    


  • Firefighter schrieb:

    Naja nicht wirklich.Was du machen könntest, wäre das selber mitzuloggen, welche Handler sich angemeldet haben, vielleicht hilft das ja was:

    public class Test : INotifyPropertyChanged
        {
            private static List<PropertyChangedEventHandler> Handler = new List<PropertyChangedEventHandler>();
    
            private event PropertyChangedEventHandler _propertyChanged;
            public event PropertyChangedEventHandler PropertyChanged
            {
                add
                {
                    this._propertyChanged += value;
                    Handler.Add(value);
                }
                remove
                {
                    this._propertyChanged -= value;
                    if (Handler.Contains(value))
                        Handler.Remove(value);
                }
    
            }
    
        }
    

    Für Debuggingzwecke sollte das reichen. Ich kann das ganze ja per #if nur im Debugmodus reinbauen. Im Release sollte sowas ja nichts mehr zu suchen haben. Besten dank.



  • CSL schrieb:

    Ich gehe davon aus das die GUI Elemente intern WeakReferences benutzen.

    Welche GUI Elemente? Hier ist ein delegate im Spiel, und der speichert keine WeakReferences.



  • Fedaykin schrieb:

    Folgendes Problem:
    Ein GUI Element hört auf PropertyChange events einer klasse. Es meldet sich also per

    MyClass.PropertyChange += new PropertyChangedEventHandler(....);
    

    auf die Events an. Prinzipiell heisst das ja, dass dieses GUI Objekt auch noch von was anderen Referenziert wird ausser der eigentlichen GUI oberfläche. Wenn ich das Element nun von der Oberfläche lösche. Wird es dann aufgrund dieser REferenz vor dem GC bewahrt?

    Ja, wird es. Du musst deine Delegates mit "-=" wieder "entfernen". Von Hand. In der Dispose Funktion.



  • hustbaer schrieb:

    CSL schrieb:

    Ich gehe davon aus das die GUI Elemente intern WeakReferences benutzen.

    Welche GUI Elemente? Hier ist ein delegate im Spiel, und der speichert keine WeakReferences.

    Ich gehe davon aus das wenn ich das hier habe:
    <Button Content="{Binding Name}" />
    und das Objekt mit dem Property "Name" wird ausgetauscht, das die Binding klasse so schlau ist und das PropertyChanged Event welches es vorher abonnierte automatisch wieder entfernt.

    Das geht indem intern ein WeakReference implementiert wurde, oder die Binding klasse entfernt es von Hand sofern der DataContext geändert wurde.

    Binding krallt sich ja automatisch das PropertyChanged aus dem Objekt im DataContext sofern es vom Typen INotifyPropertyChanged ist.



  • CSL: Weiß nicht ob du seinen Post überlesen hast, wo er geschrieben hat das er kein WPF benutzt. Oder bezog sich deine Antwort nur auf die Aussage von hustbaer?



  • CSL schrieb:

    hustbaer schrieb:

    CSL schrieb:

    Ich gehe davon aus das die GUI Elemente intern WeakReferences benutzen.

    Welche GUI Elemente? Hier ist ein delegate im Spiel, und der speichert keine WeakReferences.

    Ich gehe davon aus das wenn ich das hier habe:
    <Button Content="{Binding Name}" />
    und das Objekt mit dem Property "Name" wird ausgetauscht, das die Binding klasse so schlau ist und das PropertyChanged Event welches es vorher abonnierte automatisch wieder entfernt.

    Das geht indem intern ein WeakReference implementiert wurde, oder die Binding klasse entfernt es von Hand sofern der DataContext geändert wurde.

    Ja, es kann automatisch gehen, wenn das Framework sich darum kümmert. Wie genau spielt dabei (meist) keine Rolle.

    Da der OP den folgenden Code-Schnippel gezeigt hat

    MyClass.PropertyChange += new PropertyChangedEventHandler(....);
    

    bin ich einfach mal davon ausgegangen, dass er diesen Code selbst irgendwo stehen hat. Und sich kein Framework um irgendwas kümmern wird.



  • Ich habe die Information das Forms verwendet wird tatsächlich überlesen ^^
    Hatte auch hustbaers antworte gerade noch gesehen ^^


Anmelden zum Antworten