WPF OutOfMemory在显示图像几次后出现异常

时间:2016-02-24 18:44:55

标签: wpf image user-controls window dispose

我使用wpf创建了一个投票系统,并将wpf集装箱船模型大写。在系统中,正在使用一系列显示候选图片的用户控件。在最终用户完成投票后,系统将自动注销并等待下一个投票。在连续几次投票后,图片开始随机逐个丢失。当我检查时,这是因为内存不足异常。随着我继续对它进行压力测试,越来越多的图片开始消失。我有预感,因为系统没有处理以前的窗口和用户控件以及已显示的图片。如何处理窗口或至少确保在关闭窗口后处理已显示的图片?

1 个答案:

答案 0 :(得分:0)

你可以做的一些事情。首先是使用内存分析器。我个人喜欢RedGate ANTS Memory Profiler它会告诉你,如果你的物品被清理干净,我相信它们可以免费试用。

您的图像如何显示?窗口是否从磁盘加载它们?如果有少量图像,我建议将它们放在ResourceDictionary中,如下所示:

<BitmapImage UriSource="/MyApp.Client;component/Images/Pinned.png" x:Key="Pinned" PresentationOptions:Freeze="True" />
<BitmapImage UriSource="/MyApp.Client;component/Images//Unpinned.png" x:Key="Unpinned" PresentationOptions:Freeze="True" />

然后在你的XAML中你可以使用:

<Image Source="{StaticResource: Unpinned}"/>

这将确保您的图片仅加载一次。所有需要它的东西都会引用它。

另请注意,如果您在窗口上订阅了任何活动,则可能会阻止您的窗口关闭。窗口关闭时,您应该始终取消引用您的事件。例如:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Loaded += DoStuff();

    }

    private RoutedEventHandler DoStuff()
    {
        //some code here
    }

    protected override void OnClosing(CancelEventArgs e)
    {
        base.OnClosing(e);

        Loaded -= DoStuff();
    }
}

注意通用方法。例如,如果你这样做:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Loaded += (o, e) =>
        {
            //Do stuff here
        };

    }

}

没有办法取消引用,因为该方法是通用的,因此没有什么可以放在你的关闭中摆脱它。这是内存泄漏和防止窗口关闭的常见问题。

经常被忽视的另一个常见的是Timer类。如果启动计时器然后在不停止计时器的情况下关闭窗口,则Timer类将保留对窗口的引用,以防止它被关闭。窗户关闭时,请务必确保您的计时器停止。