c# - CollectionView.View.Refresh 上的内存泄漏

标签 c# .net wpf data-binding memory-leaks

我这样定义了我的绑定(bind):

<TreeView
        ItemsSource="{Binding UsersView.View}"
        ItemTemplate="{StaticResource MyDataTemplate}"
/>

CollectionViewSource 是这样定义的:

private ObservableCollection<UserData> users;
public CollectionViewSource UsersView{get;set;}
UsersView=new CollectionViewSource{Source=users};
UsersView.SortDescriptions.Add(
          new SortDescription("IsLoggedOn",ListSortDirection.Descending);
UsersView.SortDescriptions.Add(
          new SortDescription("Username",ListSortDirection.Ascending);

到目前为止一切顺利,按预期工作: View 首先显示按字母顺序登录的用户,然后显示未登录的用户。

但是,UserData 的 IsLoggedIn 属性每隔几秒由后台工作线程更新一次,然后代码调用:

UsersView.View.Refresh();

在 UI 线程上。

这再次按预期工作:登录的用户从 View 底部移动到顶部,反之亦然。但是:每次我在 View 上调用 Refresh 方法时,应用程序都会囤积 3.5MB 的额外内存,这些内存只会在应用程序关闭后(或在 OutOfMemoryException 之后...)释放

< p>

我做了一些研究,下面是无效修复的列表:

  • UserData 类实现 INotifyPropertyChanged
  • 更改基础用户集合根本没有任何区别:任何 IENumerable <UserData > 作为 CollectionViewSource 的源会导致问题。
    - 将 ColletionViewSource 更改为列表 <UserData >(并刷新绑定(bind))或从 ObservableCollection 继承以获取对底层 Items 集合的访问权限以对其进行排序是行不通的。

我没脑子了!帮忙?

编辑: 我找到了: Resource MyDataTemplate 包含一个绑定(bind)到 UserData 对象以显示其属性之一的 Label,UserData 对象由 TreeView 的 ItemsSource 传递下来。 Label 有一个这样定义的 ContextMenu:

 <ContextMenu Background="Transparent" Width="325" Opacity=".8" HasDropShadow="True">

      <PrivateMessengerUI:MyUserData IsReadOnly="True" >

          <PrivateMessengerUI:MyUserData.DataContext>

              <Binding Path="."/>

          </PrivateMessengerUI:MyUserData.DataContext>

     </PrivateMessengerUI:MyUserData>

</ContextMenu>

MyUserData 对象是一个 UserControl,显示 UserData 对象的所有属性。通过这种方式,用户首先只能看到用户的一条数据,然后通过右键单击可以看到所有数据。

当我从 DataTemplate 中删除 MyUserData UserControl 时,内存泄漏就消失了!我怎样才能仍然实现上面指定的行为?

最佳答案

排除内存泄漏的第一步是找到明确的来源。这并不总是很明显,有时会违背您的直觉。根据您的解释,如果删除用户控件,问题就会消失,但是当您将其放回去时,又会开始泄漏。这很可能指向该控件内的内存泄漏(尽管不一定)。也许您的控件适合 one of the many types of WPF memory leaks ,或者您有一个更经典的问题,即订阅事件但在不再需要时没有正确取消绑定(bind)(the weak event pattern 在这里很有用)。

最好的办法是使用像 .NET Memory Profiler 这样的工具或 ANTS Memory Profiler (两者都非常好并且有免费试用)。使用这些工具中的一种,找到应该消失后仍四处游荡的对象。这些工具有助于跟踪卡在您的对象上的对象链。 their sites 上有很多关于内存分析的好文章,在 SO 和广泛开放的网络上。

关于c# - CollectionView.View.Refresh 上的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2431985/

相关文章:

c# - WPF应用程序框架IView问题

c# - .NET UserControl 接受按钮最佳实践?

c# - 我应该在数据验证期间抛出什么异常

c# - 如何正确格式化 DatePicker StyleTemplate

c# - 这些人如何避免产生任何垃圾?

.net - 有什么简单的方法可以将 Criteria 转换为 HQL?

c# - 如何使用 LINQ 获取存在于一个集合中但不存在于另一个不同类型中的整数列表?

c# - 无法使用 .Net API 读取 Amazon S3 对象元数据,我做错了什么?

wpf - 如何从 ControlTemplate 检索 VisualChild

c# - 绑定(bind)命令丢失