gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 10:30:06 33 4
gpt4 key购买 nike

我的应用程序是由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/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com