c# - 用户控件在运行时动态创建,但存在内存泄漏

标签 c# wpf mvvm prism

我的应用程序是由MVVM设计的。

主窗口是MainWindow.xaml,如下所示。主窗口有两个用户控件。

顺便说一句,当更改viewmodel的属性时,将在运行时动态创建usercontrol。
但似乎我的应用程序存在内存泄漏。

MainWindow.xaml

<Window x:Class="InstanceTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:InstanceTest"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:MainWindowViewModel x:Key="MainWindowViewModel" />

    <DataTemplate x:Key="UD1">
        <ContentControl>
            <local:UserControl1></local:UserControl1>
        </ContentControl>
    </DataTemplate>

    <DataTemplate x:Key="UD2">
        <ContentControl>
            <local:UserControl2></local:UserControl2>
        </ContentControl>
    </DataTemplate>

    <DataTemplate x:Key="contentsTemplate">
        <ContentControl>
            <ContentControl.Style>
                <Style TargetType="ContentControl">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ViewType}" Value="1">
                            <Setter Property="ContentTemplate" Value="{DynamicResource UD1}" />
                        </DataTrigger>

                        <DataTrigger Binding="{Binding ViewType}" Value="2">
                            <Setter Property="ContentTemplate" Value="{DynamicResource UD2}" />
                        </DataTrigger>

                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>
    </DataTemplate>
</Window.Resources>
<Grid DataContext="{StaticResource MainWindowViewModel}">
    <StackPanel>
        <Button Height="30" Command="{Binding ChangeViewCommand}">ChangeView</Button>
        <ContentControl Content="{Binding}" ContentTemplate="{StaticResource contentsTemplate}" />
    </StackPanel>
</Grid>

MainWindow.xaml is related to MainWindowViewModel.cs. According to ViewType property, each usercontrol is created dynamically in run time.


public class MainWindowViewModel : ViewModelBase
{

    private string viewType;
    public string ViewType
    {
        get { return viewType; }
        set 
        {
            viewType = value;
            base.RaisePropertyChanged(() => this.ViewType);
        }
    }

    public MainWindowViewModel()
    {
        ChangeViewCommand = new RelayCommand(ChangeView);
    }

    public ICommand ChangeViewCommand { get; private set; }
    private void ChangeView(object o)
    {
        int aa = 1000;
        while (aa > 0)
        {
            System.Threading.Thread.Sleep(1000);

            System.Windows.Forms.Application.DoEvents();

            if (ViewType == "1")
                ViewType = "2";
            else
                ViewType = "1";
            aa--;

            //GC.Collect();
        }
    }
}

UserControl1.xaml


 <UserControl.Resources>
    <local:uc1ViewModel x:Key="uc1ViewModel" />
</UserControl.Resources>
<Grid DataContext="{StaticResource uc1ViewModel}">
    <StackPanel>
        <TextBlock FontSize="30" Text="{Binding TextExample}"></TextBlock>
        <Image Source="/InstanceTest;component/Images/sample.jpg" />
    </StackPanel>
</Grid>

UserControl1.xaml has uc1ViewModel.cs. UserControl2.xaml has uc2ViewModel.cs as below.


public class uc1ViewModel : ViewModelBase
{
    private string textExample;
    public string TextExample
    {
        get { return textExample; }
        set
        {
            textExample = value;
            base.RaisePropertyChanged(() => this.TextExample);
        }
    }

    public uc1ViewModel()
    {
        TextExample = "UD1...";
    }

    ~uc1ViewModel()
    {
        Debug.WriteLine("Call Destructor");
    }

}



MainViewModel.cs的ChangeView函数每秒更改一次ViewType属性。
更改ViewType的属性时,将ui1ViewModel创建为新实例。如果下次创建ui1ViewModel的实例,我希望ui1ViewModel的旧实例会被垃圾收集器删除。

但是,当进行大量测试时,看起来应用程序有内存泄漏。
我检查了ui1ViewModel的析构函数
然后在析构函数中键入Debug.WriteLine(“Call Destructor”)。但它不会每次都调用。
当我强制调用GC.Collect()时,将调用ui1ViewModel的析构函数,并减少应用程序的内存大小。

所以,我的问题是

在这种情况下可以强制调用GC.collect()吗?还是您有其他解决此问题的方法?

最佳答案

我也不认为这是内存泄漏:

A correctly-written program cannot assume that finalizers will ever run.



Raymond Chen对于垃圾收集对人们的误解有一个很好的解释:
http://blogs.msdn.com/b/oldnewthing/archive/2010/08/09/10047586.aspx

我将永远记住这一点:

Garbage collection is simulating a computer with an infinite amount of memory. The rest is mechanism.

关于c# - 用户控件在运行时动态创建,但存在内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8033112/

相关文章:

c# - 存储查找值的最佳方式

c# - 为什么 IE 不能将我的输出识别为 XML?

wpf - DataGrid 行的条件文本颜色?

c# - WPF ListView 标题悬停/按下颜色

wpf - 使用资源设置窗口背景颜色

c# - 属性(property)已由 'ListView' 注册

c# - 使用 MVVM-Light 这是引发事件的正确方法吗?坚持到底应该去哪里?

c# - Html.BeginForm 没有发回整个数据

wpf - 如何将此 WPF 示例进一步解耦为 MVC、MVP 或 MVVM?

c# - 将数据从 form2 传递到 form1 并将其保存在字符串变量中