如果删除了 TabItem,如何释放内存?
How to free memory if a TabItem is removed?
谁运行下面的应用程序会注意:
- Window 已经出现 ==> 内存使用量为 19.3 MB
- Select "Tab B" ==> 内存使用量上升到 40.3 MB
- 单击按钮 "Action" 删除 "Tab B" ==> 内存占用
减少到 39.4 MB
问题:如何将内存消耗减少到 19.3 MB?
应用程序代码 Xaml
:
<Window x:Class="WpfApplication2.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:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow"
FontSize="14"
WindowStartupLocation="CenterScreen"
Height="230"
Width="530"
Visibility="Visible"
Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TabControl Name="tabControl" Grid.Row="0">
<TabItem Name="tabItem_1" Header="--- Tab A ---" />
<TabItem Name="tabItem_2" Header="--- Tab B ---">
<RichTextBox Name="rtb"
IsDocumentEnabled="True"
VerticalContentAlignment="Top"
HorizontalContentAlignment="Left"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
IsReadOnly="False"
AcceptsTab="True"
Margin="5,5,5,5"
Padding="5,5,5,5"/>
</TabItem>
</TabControl>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,10,10">
<Button Name="buttonAction" Content=" _Action " Click="buttonAction_Click" />
<Button Name="buttonCancel" Content=" _Cancel " Click="buttonCancel_Click" IsCancel="True" Margin="10,0,0,0" />
</StackPanel>
</Grid>
</Window>
应用程序代码 C#
:
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// OnLoad.
/// </summary>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 6000; i++)
{
Run run = new Run("»Today is the day before tomorrow.« – »Are you sure, Mr President?« ");
Bold bold = new Bold(run);
Paragraph para = new Paragraph(bold);
if (i % 2 == 0)
para.Background = Brushes.SandyBrown;
else
para.Background = Brushes.Khaki;
rtb.Document.Blocks.Add(para);
}
rtb.Document.Blocks.Remove(rtb.Document.Blocks.FirstBlock);
tabItem_1.Focus();
}
/// <summary>
/// Button "Action".
/// </summary>
private void buttonAction_Click(object sender, RoutedEventArgs e)
{
tabControl.Items.RemoveAt(1);
}
/// <summary>
/// Button "Cancel".
/// </summary>
private void buttonCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}
.NET(通常,大多数垃圾收集环境)不会在不再使用对象时确定性地释放内存。它将项目标记为符合收集条件,并在它认为合适时释放它们(垃圾收集器中的算法考虑了很多事情:系统上的内存压力,您是否正在执行可能受到影响的其他进程收集时速度变慢等)
您可以 "semi" 通过调用 GC.Collect()
强制垃圾回收,但普遍的共识是您应该 不 这样做,除非有好的原因。确定是否需要内存以及集合的积极性的算法是由通常比您更了解的非常聪明的人制定的:-)
如果你有内存问题(有内存问题意味着你 运行 系统内存不足,而不是你的进程使用的内存比你认为的多),那么是时候找到"leaks",或者阻止垃圾收集器完成其工作的其他不需要的对象引用......但是如果你没有这些问题,那么任务管理器中进程占用的内存就不足以成为思考的理由它没有正常工作。
此外,.NET CLR 在本机堆上保留内存以更快地进行托管分配和释放(这基本上就是任务管理器向您展示的内容,即 CLR 为您的进程分配了多少内存),这是什么叫做"managed heap"。因此,即使垃圾收集器实际上释放了您的控制权,一般来说,除非有理由不这样做,否则它会为您的进程保留一些内存,以便如果您需要创建其他托管对象,它会把该保留内存中的那些对象:同样,除非有理由不保留该内存(例如:系统 运行ning 内存不足),您看到它在任务管理器上分配的事实无关紧要,并不意味着它没有发挥作用。
更多基础文献给尊:
谁运行下面的应用程序会注意:
- Window 已经出现 ==> 内存使用量为 19.3 MB
- Select "Tab B" ==> 内存使用量上升到 40.3 MB
- 单击按钮 "Action" 删除 "Tab B" ==> 内存占用 减少到 39.4 MB
问题:如何将内存消耗减少到 19.3 MB?
应用程序代码 Xaml
:
<Window x:Class="WpfApplication2.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:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow"
FontSize="14"
WindowStartupLocation="CenterScreen"
Height="230"
Width="530"
Visibility="Visible"
Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TabControl Name="tabControl" Grid.Row="0">
<TabItem Name="tabItem_1" Header="--- Tab A ---" />
<TabItem Name="tabItem_2" Header="--- Tab B ---">
<RichTextBox Name="rtb"
IsDocumentEnabled="True"
VerticalContentAlignment="Top"
HorizontalContentAlignment="Left"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
IsReadOnly="False"
AcceptsTab="True"
Margin="5,5,5,5"
Padding="5,5,5,5"/>
</TabItem>
</TabControl>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,10,10">
<Button Name="buttonAction" Content=" _Action " Click="buttonAction_Click" />
<Button Name="buttonCancel" Content=" _Cancel " Click="buttonCancel_Click" IsCancel="True" Margin="10,0,0,0" />
</StackPanel>
</Grid>
</Window>
应用程序代码 C#
:
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// OnLoad.
/// </summary>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 6000; i++)
{
Run run = new Run("»Today is the day before tomorrow.« – »Are you sure, Mr President?« ");
Bold bold = new Bold(run);
Paragraph para = new Paragraph(bold);
if (i % 2 == 0)
para.Background = Brushes.SandyBrown;
else
para.Background = Brushes.Khaki;
rtb.Document.Blocks.Add(para);
}
rtb.Document.Blocks.Remove(rtb.Document.Blocks.FirstBlock);
tabItem_1.Focus();
}
/// <summary>
/// Button "Action".
/// </summary>
private void buttonAction_Click(object sender, RoutedEventArgs e)
{
tabControl.Items.RemoveAt(1);
}
/// <summary>
/// Button "Cancel".
/// </summary>
private void buttonCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}
.NET(通常,大多数垃圾收集环境)不会在不再使用对象时确定性地释放内存。它将项目标记为符合收集条件,并在它认为合适时释放它们(垃圾收集器中的算法考虑了很多事情:系统上的内存压力,您是否正在执行可能受到影响的其他进程收集时速度变慢等)
您可以 "semi" 通过调用 GC.Collect()
强制垃圾回收,但普遍的共识是您应该 不 这样做,除非有好的原因。确定是否需要内存以及集合的积极性的算法是由通常比您更了解的非常聪明的人制定的:-)
如果你有内存问题(有内存问题意味着你 运行 系统内存不足,而不是你的进程使用的内存比你认为的多),那么是时候找到"leaks",或者阻止垃圾收集器完成其工作的其他不需要的对象引用......但是如果你没有这些问题,那么任务管理器中进程占用的内存就不足以成为思考的理由它没有正常工作。
此外,.NET CLR 在本机堆上保留内存以更快地进行托管分配和释放(这基本上就是任务管理器向您展示的内容,即 CLR 为您的进程分配了多少内存),这是什么叫做"managed heap"。因此,即使垃圾收集器实际上释放了您的控制权,一般来说,除非有理由不这样做,否则它会为您的进程保留一些内存,以便如果您需要创建其他托管对象,它会把该保留内存中的那些对象:同样,除非有理由不保留该内存(例如:系统 运行ning 内存不足),您看到它在任务管理器上分配的事实无关紧要,并不意味着它没有发挥作用。
更多基础文献给尊: