如何在应用程序关闭之前释放控制内存不足?

时间:2014-06-13 10:21:27

标签: c# wpf xaml finalizer

我的性能问题非常糟糕。我目前正在开发一个多窗口应用程序,但当我关闭其中一个窗口时,没有内存被释放。

甚至还有我在代码中实例化的控件,在我使用它们之后,我为它们的字段分配了null,但没有。 GC拒绝收集控件,尽管不再有参考。

Google搜索该问题会将我带到Application.ExitDispatcher.ShutdownStarted,但它们无法解决我的问题,导致应用程序继续运行。

我做了一个小样本来向你展示我的问题:

MainPage.xaml

    <Window x:Class="FinalizerSampleProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:FinalizerSampleProject"
        Title="MainWindow" Height="350" Width="525">
    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Button Content="Get rid of the custom control!" Grid.Row="1" Click="Button_Click" x:Name="DummyButton" />
    </Grid>
</Window>

MainPage.xaml.cs

using System;
using System.Windows;

namespace FinalizerSampleProject
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private CustomControl control = new CustomControl();

    public MainWindow()
    {
        InitializeComponent();
        LayoutRoot.Children.Add(control);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (control != null)
        {
            LayoutRoot.Children.Remove(control);
            control = null;
            DummyButton.Content = "Show how many instances of CustomControl still exist.";
            GC.Collect();
        }
        else
        {
            MessageBox.Show(CustomControl.InstanceCounter.ToString());
        }
    }
}

}

CustomControl.xaml

 <UserControl x:Class="FinalizerSampleProject.CustomControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Background="LightGreen">
        <TextBlock Text="Hi, I'm a custom control!"/>
</UserControl>

CustomControl.xaml.cs

using System.Windows.Controls;

namespace FinalizerSampleProject
{
/// <summary>
/// Interaction logic for CustomControl.xaml
/// </summary>
public partial class CustomControl : UserControl
{
    public static int InstanceCounter = 0;
    public CustomControl()
    {
        InstanceCounter++;
        InitializeComponent();
    }

    ~CustomControl()
    {
        InstanceCounter--;
    }
}
}

如果你试试,你会发现这个计数器每次看起来都是“一”。我不知道如何摆脱那个对象实例。

1 个答案:

答案 0 :(得分:1)

注意:此答案仅适用于有关WinForms UserControl的问题。


您的自定义控件可能会按照应有的方式处理和“释放”。只是你的终结器代码没有被调用,因为当UserControl被释放时它告诉垃圾收集器不要调用它的终结器。

这是禁止调用终结函数的标准Dispose实现:

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

该代码来自System.ComponentModel.Component。您的CustomControl课程来自UserControl

GC.SuppressFinalize(this)是阻止你的计数器减少的原因。不过不用担心,实例会被处理(并由GC收集)。

请改为尝试:

public static int InstanceCounter = 0;
private bool disposed;

public CustomControl()
{
    InstanceCounter++;
    InitializeComponent();
}

protected override void Dispose(bool disposing)
{
    if (disposing && !this.disposed)
    {
        InstanceCounter--;
        this.disposed = true;
    }
}