了解内存泄漏

时间:2019-01-07 10:48:53

标签: c# wpf data-binding memory-leaks

我正在尝试了解WPF内存泄漏,并且在阅读了该主题之后,我仍有一些不清楚的地方。

问题最好来自示例,所以让我们定义:

型号:

public class Mom : INotifyPropertyChanged
{
   public ObservableCollection<Kid> Kids { get; set; }

   private string name;
   public string Name
   {
       get => name;
       set => Set(ref name, value);
   }

   public event PropertyChangedEventHandler PropertyChanged;

   protected void Set<T>(ref T field, T newValue = default(T), [CallerMemberName] string propertyName = null)
   {
       field = newValue;
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
   }
}

ViewModel(DataContext)可能看起来像这样:

public class MomViewModel, INotifyPropertyChanged
{
   private Mom selected;
   public Mom Selected
   {
       get => selected;
       set => Set(ref selected, value);
   }
}

现在我想问有关XAML中这两种绑定方案的问题:

第一次绑定:

<ListView ItemsSource="{Binding Selected.Kids}">
...
</ListView >

第二次绑定:

<TextBlock Text="{Binding Selected.Kids.Count}" />

现在想象一下,在ViewModel中,我们有一个计时器,它每秒分配一个新的Mom。那就是Selected = new Mom { .. };

第一季度: 绑定1会产生内存泄漏吗?该属性的类型为ObservableCollection,它实现了InotifyPropertyChanged,但该属性本身却没有(只是常规的get,set)。

第二季度: 绑定2会产生内存泄漏吗?绑定直接针对Count,后者来自Collection,并且未实现INotifyPropertyChanged。

请注意,视图(XML)本身从未被破坏-每秒仅更改一次“ Selected”属性。 WPF允许进行垃圾回收(这也仅在视图被破坏或绑定发生更改时)对我来说还是不清楚的。我的测试在这里没有定论...

谢谢。

2 个答案:

答案 0 :(得分:0)

在下面的示例代码中,将Mom的source属性设置为新的Selected对象之后,无论您是否绑定了Mom的先前实例,都可以进行垃圾回收到Selected.KidsSelected.Kids.Count

public sealed class MomViewModel : INotifyPropertyChanged, IDisposable
{
    private readonly System.Timers.Timer _timer = new System.Timers.Timer();

    public MomViewModel()
    {
        _timer.Interval = 2000;
        _timer.Elapsed += (s, e) => Selected = new Mom();
        _timer.Start();
    }

    private Mom selected;
    public Mom Selected
    {
        get => selected;
        set => Set(ref selected, value);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void Set<T>(ref T field, T newValue = default(T), [CallerMemberName] string propertyName = null)
    {
        field = newValue;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public void Dispose()
    {
        _timer.Dispose();
    }
}

通过在视图中设置以下绑定,不会引入任何内存泄漏:

<ListView ItemsSource="{Binding Selected.Kids}" />
<TextBlock Text="{Binding Selected.Kids.Count}" />

答案 1 :(得分:0)

您所拥有的WPF特定部件中的任何一个都不会导致内存泄漏。

WPF绑定是弱引用,因此它们本质上不会保持活动。 如果绑定到未实现inotifypropertychanged的poco,则可能会导致内存泄漏。你避免了。 是否筹集在二传手中更改的财产无关紧要。因此,count也不会导致任何内存泄漏。

如果您在任何地方都遇到问题,则很有可能是如何保留对这些妈妈的每一个的参考,而您要每秒更新一次。仍然有一些关于这些的参考,并且不允许它超出范围。解决方法可能很简单,例如将年迈的妈妈带出可观察的收集物并进行处理。

如果您想确切地了解阻止事情在复杂的企业级应用中被垃圾收集的原因,那么可以尝试redgate Ants profiler。有免费试用。