琐碎的WPF应用程序中的不受管理的泄漏 [英] Unmanaged leak in a trivial WPF application

查看:86
本文介绍了琐碎的WPF应用程序中的不受管理的泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当鼠标移到WPF应用上时,我遇到了泄漏非托管内存的情况.具体来说,当我在perfmon或Red Gate的内存分析器中对应用程序进行性能分析时,专用字节单调增加,但是所有托管堆中的字节保持不变-我认为这意味着该应用程序具有非托管泄漏.

我已经创建了一个简单的repro应用程序,但是我看不出问题出在哪里.

该应用程序由一个包含四个项的ListView组成.将鼠标快速移到这些项目上会导致问题.

如果您有兴趣重现此问题,请使用以下代码-它不漂亮,但很简单.

谢谢


修改:我创建了一个

App.xaml.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;

namespace WpfLeakRepro
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
    }
}

Generic.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <LinearGradientBrush x:Key="ListItemHover"
                         EndPoint="0,1"
                         StartPoint="0,0">
        <GradientStop Color="Aqua"
                      Offset="0" />
        <GradientStop Color="White"
                      Offset="1" />
    </LinearGradientBrush>
    <LinearGradientBrush x:Key="ListItemSelected"
                         EndPoint="0,1"
                         StartPoint="0,0">
        <GradientStop Color="Blue"
                      Offset="0" />
        <GradientStop Color="White"
                      Offset="1" />
    </LinearGradientBrush>
    <VisualBrush x:Key="CheckeredBackground"
                 Viewport="20,20,20,20"
                 ViewportUnits="Absolute"
                 TileMode="Tile"
                 Stretch="Fill">
        <VisualBrush.Visual>
            <Canvas Opacity="5">
                <Rectangle Fill="#FF606060"
                           Height="21"
                           Width="21"
                           Canvas.Top="20" />
                <Rectangle Fill="#FF606060"
                           Width="21"
                           Height="21"
                           Canvas.Left="20" />
                <Rectangle Fill="#FF646464"
                           Height="21"
                           Width="21"
                           Canvas.Left="20"
                           Canvas.Top="20" />
                <Rectangle Fill="#FF646464"
                           Width="21"
                           Height="21" />
            </Canvas>
        </VisualBrush.Visual>
    </VisualBrush>
    <Style TargetType="{x:Type ListViewItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListViewItem}">
                    <Border Background="{TemplateBinding Background}">
                        <Grid>
                            <GridViewRowPresenter />
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"
                                 Value="true">
                            <Setter Property="Background"
                                    Value="{DynamicResource ListItemHover}" />
                        </Trigger>
                        <Trigger Property="IsSelected"
                                 Value="true">
                            <Setter Property="Background"
                                    Value="{DynamicResource ListItemSelected}" />
                        </Trigger>
                    </ControlTemplate.Triggers>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Window1.xaml

<Window x:Class="WpfLeakRepro.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="449" Width="497">
    <Grid>
        <ListView Margin="12"
                  Name="listView"
                  ItemsSource="{Binding}">
            <ListView.View>
                <GridView>
                    <GridView.Columns>
                        <GridViewColumn Header="File Name">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Name}" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Thumbnail">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <Border Background="{DynamicResource CheckeredBackground}" Width="72" Height=48/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView.Columns>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

Window1.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.IO;

namespace WpfLeakRepro
{
    public class Picture
    {
        public string Name { get; set; }
    }

    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            List<Picture> pictures = new List<Picture>();

            string[] images = new string[] {"Blue hills.jpg", "Sunset.jpg", "Water lilies.jpg", "Winter.jpg" };

            foreach (string imagePath in images)
            {
                pictures.Add(new Picture() { Name = imagePath });
            }

            DataContext = pictures;
        }
    }
}

此问题似乎与用于方格背景的VisualBrush有关.用SolidColorBrush替换它,问题就消失了.但这并不重要:Microsoft的人员建议我安装.NetFx 3.5sp1的最新升级,这似乎可以解决问题(更多详细信息,请参见Microsoft Connect issue for this problem.


App.xaml

<Application x:Class="WpfLeakRepro.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Generic.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

App.xaml.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;

namespace WpfLeakRepro
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
    }
}

Generic.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <LinearGradientBrush x:Key="ListItemHover"
                         EndPoint="0,1"
                         StartPoint="0,0">
        <GradientStop Color="Aqua"
                      Offset="0" />
        <GradientStop Color="White"
                      Offset="1" />
    </LinearGradientBrush>
    <LinearGradientBrush x:Key="ListItemSelected"
                         EndPoint="0,1"
                         StartPoint="0,0">
        <GradientStop Color="Blue"
                      Offset="0" />
        <GradientStop Color="White"
                      Offset="1" />
    </LinearGradientBrush>
    <VisualBrush x:Key="CheckeredBackground"
                 Viewport="20,20,20,20"
                 ViewportUnits="Absolute"
                 TileMode="Tile"
                 Stretch="Fill">
        <VisualBrush.Visual>
            <Canvas Opacity="5">
                <Rectangle Fill="#FF606060"
                           Height="21"
                           Width="21"
                           Canvas.Top="20" />
                <Rectangle Fill="#FF606060"
                           Width="21"
                           Height="21"
                           Canvas.Left="20" />
                <Rectangle Fill="#FF646464"
                           Height="21"
                           Width="21"
                           Canvas.Left="20"
                           Canvas.Top="20" />
                <Rectangle Fill="#FF646464"
                           Width="21"
                           Height="21" />
            </Canvas>
        </VisualBrush.Visual>
    </VisualBrush>
    <Style TargetType="{x:Type ListViewItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListViewItem}">
                    <Border Background="{TemplateBinding Background}">
                        <Grid>
                            <GridViewRowPresenter />
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"
                                 Value="true">
                            <Setter Property="Background"
                                    Value="{DynamicResource ListItemHover}" />
                        </Trigger>
                        <Trigger Property="IsSelected"
                                 Value="true">
                            <Setter Property="Background"
                                    Value="{DynamicResource ListItemSelected}" />
                        </Trigger>
                    </ControlTemplate.Triggers>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Window1.xaml

<Window x:Class="WpfLeakRepro.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="449" Width="497">
    <Grid>
        <ListView Margin="12"
                  Name="listView"
                  ItemsSource="{Binding}">
            <ListView.View>
                <GridView>
                    <GridView.Columns>
                        <GridViewColumn Header="File Name">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Name}" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Thumbnail">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <Border Background="{DynamicResource CheckeredBackground}" Width="72" Height=48/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView.Columns>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

Window1.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.IO;

namespace WpfLeakRepro
{
    public class Picture
    {
        public string Name { get; set; }
    }

    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            List<Picture> pictures = new List<Picture>();

            string[] images = new string[] {"Blue hills.jpg", "Sunset.jpg", "Water lilies.jpg", "Winter.jpg" };

            foreach (string imagePath in images)
            {
                pictures.Add(new Picture() { Name = imagePath });
            }

            DataContext = pictures;
        }
    }
}

解决方案

The issue appears to have something to do with the VisualBrush that was being used for the checkered background. Replace this with a SolidColorBrush, and the issue goes away. But it really doesn't matter: the folks at Microsoft suggested that I install the latest upgrades to .NetFx 3.5sp1, and this seems to fix the problem (more details here).

这篇关于琐碎的WPF应用程序中的不受管理的泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆