WPF 窗口关闭后,为什么内存不释放

dangdang2471 2021-04-15 05:11:39
1. 有主窗口A,只有一个Button
2. 和子窗口B,有100个TextBox控件
3. 在窗口A中,有一个循环,不停创建和显示(ShowDialog)窗口B
4. 窗口B显示出来后,立即把自己Close

问题是:窗口B关闭后,内存并没有回收,直到第975次循环时发生 OutOfMemoryException 异常。
不明白为何发生这样的问题,代码中并没有用到任何非托管对象。
请教如何解决此问题?

下面是代码:
A窗口:(MainWindow)
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Margin="100" Content="0" Click="Button_Click"></Button>
</Grid>
</Window>


/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

private void Button_Click(object sender, RoutedEventArgs e)
{
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
var num = 0;
var count = 0;
while (true)
{
this.Dispatcher.Invoke((Action)(() =>
{
try
{
var v = new TestWindow { Owner = this };
v.ShowDialog();

((Button)sender).Content = num;
count = Application.Current.Windows.Count;

//GC.Collect(); // 无效
//GC.WaitForPendingFinalizers(); // 无效

Thread.Sleep(1);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}));

Console.WriteLine(string.Format("Num={0} Count={1}", num++, count));
}
});
}
}


B窗口:(TestWindow)
<Window x:Class="WpfApplication2.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" WindowStartupLocation="CenterScreen" Height="300" Width="300" ContentRendered="Window_ContentRendered">
<Grid>
<StackPanel>
<Button Content="关闭" Click="Button_Click"></Button>
<StackPanel>
<StackPanel>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
<TextBox Text="A"></TextBox>
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
</Window>


    /// <summary>
/// TestWindow.xaml 的交互逻辑
/// </summary>
public partial class TestWindow : Window
{
public TestWindow()
{
InitializeComponent();
}

private void Button_Click(object sender, RoutedEventArgs e)
{
this.Close();
}

private void Window_ContentRendered(object sender, EventArgs e)
{
this.Close();
}
}
...全文
5738 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
不耻上问 2021-10-18
  • 打赏
  • 举报
回复

楼主,这个问题解决了吗

dangdang2471 2021-06-16
  • 打赏
  • 举报
回复

改版了?找不到“结帖”入口!?

dangdang2471 2021-05-18
  • 打赏
  • 举报
回复
引用 10 楼 KnightWelling 的回复:
不知道你到底是如何测试的。这段代码根本不存在什么内存泄漏,也不存在无法回收的问题,这个问题的本质其实是垃圾回收问题。建议多了解下垃圾回收机制。
c#的垃圾回收不应该是在后台默默进行的吗?代码中只要做到对非托管资源保证释放就行了,我认为程序员应避免干预垃圾回收。
dangdang2471 2021-05-18
  • 打赏
  • 举报
回复
引用 10 楼 KnightWelling 的回复:
不知道你到底是如何测试的。这段代码根本不存在什么内存泄漏,也不存在无法回收的问题,这个问题的本质其实是垃圾回收问题。建议多了解下垃圾回收机制。
可能就是垃圾回收的问题,请问该如何做能避免报OutOfMemoryException?
KnightWelling 2021-04-22
  • 打赏
  • 举报
回复
不知道你到底是如何测试的。这段代码根本不存在什么内存泄漏,也不存在无法回收的问题,这个问题的本质其实是垃圾回收问题。建议多了解下垃圾回收机制。
wang_peng 2021-04-16
  • 打赏
  • 举报
回复
那肯定是有线程没释放干净。在关闭事件里 Process.GetCurrentProcess().Kill(); 试试这个
dangdang2471 2021-04-16
  • 打赏
  • 举报
回复
又测试了一次,放入byte[1024*1024*10]没有任何变化, 改为byte[1024*1024*100]依然没变。 当窗口中TextBox改为10个时,内存回收正常。 改成100个时,运行一会报OutOfMemoryException
晨易夕 2021-04-16
  • 打赏
  • 举报
回复
那大概也是wpf 的control导致的内存泄漏的问题。 你可以做个测试,在B窗体中放一个byte[1024*1024*10] 当界面没有文本框或其他导致内存泄漏的控件时,窗体关闭B无引用后,内存会回收。 如果放入textbox,你大概能看到内存呈10M的上升趋势,直到OutOfMemoryException。
dangdang2471 2021-04-16
  • 打赏
  • 举报
回复
这个问题和您上面链接中提到的TextBox的内存泄漏貌似还不一样。 把TextBox换成TextBlock,数量扩大10倍,也会 OutOfMemoryException。 所以和界面占用的内存数量有关,如果界面较小、较简单,则垃圾回收可以正常工作,可以观察到内存涨涨跌跌。当界面大小超过某个阈值时,则垃圾回收疑似停止,内存不断上涨,直到崩溃。
晨易夕 2021-04-16
  • 打赏
  • 举报
回复 1
这大概就是传说中WPF TextBox导致的内存泄漏的问题了,之前在网上也见过这样的说法。 看这个:https://marlongrech.wordpress.com/2008/02/16/wpf-textbox-memory-leak/ 你如果把窗体中的文本框全部去掉,大概不会出现这样的问题。
dangdang2471 2021-04-15
  • 打赏
  • 举报
回复
WPF的窗口,没有Dispose() 方法呀
wanghui0380 2021-04-15
  • 打赏
  • 举报
回复
close 也只是close,不是Dispose 对比一下 xxxForm x=new xxxForm() x.show(); x.close() x.show() 你看到了,show显示了,close关闭,然后我又show了,这说明啥,说明这个x本身存在 所以你需要做的一件事情是,告诉gc我不用了 x.Dispose() x=null
dangdang2471 2021-04-15
  • 打赏
  • 举报
回复
环境:Win 10 + VS2010

17,741

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 .NET Framework
社区管理员
  • .NET Framework社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧