Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Usercontrols是在运行时动态创建的,但存在内存泄漏_C#_Wpf_Mvvm_Prism - Fatal编程技术网

C# Usercontrols是在运行时动态创建的,但存在内存泄漏

C# Usercontrols是在运行时动态创建的,但存在内存泄漏,c#,wpf,mvvm,prism,C#,Wpf,Mvvm,Prism,我的应用程序是由MVVM设计的 主窗口是MainWindow.xaml,如下所示。主窗口有两个用户控件 顺便说一下,当viewmodel的属性更改时,usercontrol在运行时动态创建。 但我的应用程序似乎有内存泄漏 main window.xaml <Window x:Class="InstanceTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml

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

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

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

main window.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>
UserControl1.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>

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

但是,在多次测试时,应用程序似乎存在内存泄漏。 我检查了ui1ViewModel的析构函数 然后在析构函数处键入Debug.WriteLine(“调用析构函数”)。但它并不是每次都打电话。 当我强制调用GC.Collect()时,会调用ui1ViewModel的析构函数并减少应用程序的内存大小

所以,我的问题是


在这种情况下,我可以强制调用GC.collect()吗?或者你有其他方法来解决这个问题吗?

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

正确编写的程序不能假定终结器将 跑

雷蒙德·陈(Raymond Chen)对人们对垃圾收集的错误理解有一个很好的解释:

我会永远记住这一点:

垃圾收集是模拟一台拥有无限数量垃圾的计算机 记忆。剩下的就是机制


请阅读DataContext=“{StaticResource uc1ViewModel}”,uc1ViewModel每次都被分配。那么我必须调用GC.Collect()才能避免内存泄漏吗?不,事实上,手动调用GC.Collect无法防止内存泄漏。请阅读我上次评论中提供的链接。您很可能没有内存泄漏。如果你感到震惊,你有一个,然后配置你的内存消耗很长时间我担心内存泄漏的原因是我已经测试了很长时间。应用程序的内存从25M开始。除手动GC.Collect()外,内存最大为35M。我已经用Windbg和profiler查找了这个程序,以找到原因。@Dianwater-我已经检查了您的示例,没有任何内存泄漏。要知道GC会根据需要保留内存。这取决于您的系统配置、可用内存、内存使用情况等。在适当的情况下,查看200+mb的保留内存并不奇怪。
 <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>
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");
    }

}