首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >棱镜的DelegateCommand内存泄漏

棱镜的DelegateCommand内存泄漏
EN

Stack Overflow用户
提问于 2015-12-09 20:48:45
回答 2查看 1.1K关注 0票数 2

使用此代码,您可以100%地再现我的问题。我创建了一个“父”ViewModel:

代码语言:javascript
复制
using Prism.Commands;
using Prism.Mvvm;
using System.Collections.ObjectModel;

namespace WpfApplication1 {
    public class ViewModel : BindableBase {

        public ObservableCollection<ChildViewModel> Items { get; set; }

        public DelegateCommand<ChildViewModel> CloseItem { get; set; }

        public ViewModel() {
            CloseItem = new DelegateCommand<ChildViewModel>(OnItemClose);

            Items = new ObservableCollection<ChildViewModel>(new[] {
                new ChildViewModel { Name = "asdf" },
                new ChildViewModel { Name = "zxcv" },
                new ChildViewModel { Name = "qwer" },
                new ChildViewModel { Name = "fdgz" },
                new ChildViewModel { Name = "hgjkghk" }
            });
        }

        private void OnItemClose(ChildViewModel obj) {
            Items.Remove(obj);
        }
    }
}

它包含一个ObservableCollection of ChildViewModel实例:

代码语言:javascript
复制
using Prism.Mvvm;

namespace WpfApplication1 {
    public class ChildViewModel : BindableBase {

        public string Name { get; set; }
        protected byte[] leakArr = new byte[1024 * 1024 * 10];

    }
}

如您所见,我在每个ChildViewModel中声明了一个10 As数组。现在的观点是:

代码语言:javascript
复制
public partial class MainWindow : Window {
    public MainWindow() {
        InitializeComponent();

        DataContext = new ViewModel();
    }
}

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <TabControl ItemsSource="{Binding Items}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <DockPanel>
                    <TextBlock Text="{Binding Path=Name}" DockPanel.Dock="Left" Margin="2,3,0,2" />
                    <Button DockPanel.Dock="Right" BorderThickness="0" Background="Transparent" 
                            Margin="10,2,2,2" 
                            Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}, Path=DataContext.CloseItem}" 
                            CommandParameter="{Binding}">
                        <Button.Content>
                            <TextBlock FontWeight="Bold" Text="X" />
                        </Button.Content>
                    </Button>
                </DockPanel>
            </DataTemplate>
        </TabControl.ItemTemplate>
    </TabControl>
</Window>

查看VS2015内存诊断工具,我可以看到,即使每个ChildViewModel都已从Items集合中删除,它仍然存在于内存中,其中有一个对象(对于每个vm)仍然持有对它的引用--一个Button控件。有趣的是,如果我将Button的命令声明替换为:

代码语言:javascript
复制
Click="Button_Click"

private void Button_Click(object sender, RoutedEventArgs e) {
            (DataContext as ViewModel).CloseItem.Execute(((sender as Button).DataContext as ChildViewModel));
        }

没有内存泄漏--这意味着调试工具没有显示任何已处理的ChildViewModel实例。我不知道这是棱镜特有的问题,还是某种wpf的怪癖。

我正在使用.net和棱镜库的最新版本。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-10 15:00:32

我似乎找到了解决这个问题的方法(至少在我的应用程序中)--我停止了直接绑定到ChildViewModel实例,而是将CommandParameter绑定到ChildViewModelName属性。然后,在ViewModel中,我只需要遍历项集合并删除具有匹配属性值的项。现在VS诊断工具没有显示任何对象,这些对象应该是GCed,而不是,因此内存泄漏消失了。

棱镜小组正在分析这个问题:https://github.com/PrismLibrary/Prism/issues/345

票数 2
EN

Stack Overflow用户

发布于 2015-12-09 21:59:43

您是否检查了自定义ICommand实现是否具有相同的行为?

因为相关的错误,当我们删除弱引用时,我们可能引入了这个内存泄漏。

请将此问题报告如下:

https://github.com/PrismLibrary/Prism/issues

我们将进行调查,并对此进行调查。

编辑:我很高兴听到这不是棱镜问题:)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34188671

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档