Geronimo18
Geronimo18

Reputation: 410

Silverlight memory leak

well,i tried this and the memory profiler shows that the problem still not solved, actually i removed the I was creating a DependencyProperty Changed with a callback method using the following code:

public void RegisterForNotification(string propertyName, FrameworkElement element, PropertyChangedCallback callback) 
{ 
    Binding b = new Binding(propertyName) { Source = element }; 
    var prop = System.Windows.DependencyProperty.RegisterAttached( 
        "ListenAttached" + propertyName, 
        typeof(object), 
        typeof(UserControl), 
        new System.Windows.PropertyMetadata(callback));              
    element.SetBinding(prop, b); 
}  

well,i tried this and the memory profiler shows that the problem still not solved, actually i removed the element.SetBinding(prop, b); and the memory leak still happen so i thisnk the cause of it is not the binding it self but this code: var prop = System.Windows.DependencyProperty.RegisterAttached( "ListenAttached" + propertyName, typeof(object), typeof(UserControl), new System.Windows.PropertyMetadata(callback));
when i use null instead of callback the leak didnt happen. that means that the cause is the callback method not binding,is there any way to unregister it? or register it in another way so it doesnt cause the leak?

Thanks alot Phil Sandler it realy helps and work fine

i was trying to add visibilitychanged listener to my user control so i call the method as RegisterForNotification("Visibility", this,callback),that was causing the memory leak,

i used what you sugested like this:

public string ListenAttachedVisibility { get { return (string)GetValue(SelectedValueBindingProperty); } set { SetValue(SelectedValueBindingProperty, value); } }

    public static readonly DependencyProperty ListenAttachedVisibilityProperty =
 DependencyProperty.Register("ListenAttachedVisibility", typeof(object), typeof(UserControl),
 new System.Windows.PropertyMetadata(null, new PropertyChangedCallback(OnVisibilityChanged)));

    private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {


        // call to instance method 
        ((DualLOV)d).OnVisibilityChanged(e);
    }
    protected virtual void OnVisibilityChanged(DependencyPropertyChangedEventArgs e)
    {
        ClearValues(e.NewValue);
    }

and then i made the binding: Binding b = new Binding("Visibility") { Source = this }; this.SetBinding(ListenAttachedVisibilityProperty, b);

and the visibilty changed event worked fine also the memory leak disappeared. thanks again.

Upvotes: 1

Views: 1389

Answers (2)

Phil Sandler
Phil Sandler

Reputation: 28016

Your original (pre-edit) post seems to indicate that you have a memory leak. I'm guessing the problem is you create a Dependency Properties as an instance variable. You never want to do this, and it will cause memory leaks.

Edit:

It's not clear to me what you are trying to do. But your Dependency Property should be declared at the class level, and it should be static readonly.

It makes sense that removing the callback fixes the leak, as the callback is a "short-lived subscriber" and the DP is a "long-lived publisher". The DP is long-lived because the framework doesn't know how to clean it up, as the framework expects the DP to be declared static readonly (I can't explain why, that's just the way it works in Silverlight).

It looks like you are trying to do something with dynamic binding or notification. Whether what you are trying to do it possible or not is the subject of another question, but whatever the solution, it must be based on properly used (and declared) Dependency Properties.

Upvotes: 1

Maxim V. Pavlov
Maxim V. Pavlov

Reputation: 10509

The BindingOperations.ClearBinding() method calls ClearValue() internally. We know that by looking it up in Reflector.

public static void ClearBinding(DependencyObject target, DependencyProperty dp)
{
    if (target == null)
    {
        throw new ArgumentNullException("target");
    }
    if (dp == null)
    {
        throw new ArgumentNullException("dp");
    }
    if (IsDataBound(target, dp))
    {
        target.ClearValue(dp);
    }
}

You can use the same method in your class.

P.S. The answer is borrowed from this question.

Upvotes: 0

Related Questions