WPF - 带OpacityMask / VisualBrush的边框:内存泄漏

时间:2011-06-07 17:52:21

标签: memory-leaks binding visualbrush opacitymask

关于我的应用的简短说明:

我正在处理的应用程序是这样的贺卡设计师。想象一下,有一个背景图像,以及无限数量的“图层”(特别是图片),它们可以移动,调整大小,前后移动等等......

也可以将特定形状应用于这些层,如星形,椭圆形等。制作卡片后,可以保存为jpeg文件。

问题

一切正常,但我发现当一个形状应用于图层时,会产生内存泄漏。

以下是每个图层的UserControl代码:

<UserControl>
.....
    <Grid x:Name="_myGrid"  >
        <Border x:Name="im_the_problem" BorderThickness="0" OpacityMask="{Binding Path=MyMask.Data, Converter={StaticResource MaskConverter}}">
        <!-- My Image... -->
        </Border>
    </Grid>
</UserControl>

其中MaskConverter代码如下:

public class MaskConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter,
       System.Globalization.CultureInfo culture)
    {
        String maskData = value as String;
        if (maskData == null) 
            return null;
        if (maskData == "")
            return null;
        VisualBrush vb = new VisualBrush();
        vb.Visual = XamlReader.Parse(maskData) as Visual;
        return vb;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

参数“MyMask.Data”是一个XAML Path (我正在申请的形状),我从包含不同形状的文本文件中加载。

所以,原则是如果我有名为 * im_the_problem * 的边框,则不会释放内存。如果我发表评论 * im_the_problem * (所以我只会有没有形状的矩形图层/图片),所有内容都像魅力一样,没有内存泄漏。

问题应该在OpacityMask + VisualBrush中。

我做错了吗? 或者是否存在已知问题?有没有办法以不同的方式做同样的事情(将形状应用于图片......)?

感谢。

3 个答案:

答案 0 :(得分:0)

您可以尝试将MyMask.Data绑定到实际的Path.Data,并将Path.Fill设置为从图像创建的ImageBrush?

答案 1 :(得分:0)

您需要冻结VisualBrush;)

答案 2 :(得分:0)

我在DataGrid的列模板中遇到此问题,我在<Canvas><Path /></Canvas>中使用VisualBrush(作为静态资源)(也是静态 - 资源)并将其用作OpacityMask的{​​{1}}。每当重新加载DataGrid时,Rectangle都不会释放RectangleVisualBrush的引用,我使用内存分析工具来揭示所有OpacityMask个对象都是使用大量内存。

我不明白为什么或如何发生这种情况 - 但我很高兴我并不孤单(即使我在6.5年后遇到同样的问题......)。

我的XAML是这样的:

VisualBrush

我读到设置<DataGrid.Resources> <Canvas x:Key="icon" ...> <Path ... /> </Canvas> <VisualBrush x:Key="iconBrush" Stretch="Uniform" Visual="{StaticResource icon}" /> </DataGrid.Resources> <DataGrid.Columns> <DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Rectangle Fill="{Binding Foreground, ElementName=myDataGrid}" Width="14" Height="14" Margin="4" Visibility="{Binding IconVisibility}" OpacityMask="{StaticResource iconBrush}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> ... </DataGrid.Columns> (使用此技术完成:https://www.codeproject.com/Tips/72221/Freeze-brushes-directly-in-the-XAML-to-improve-you)将有助于Brushes的内存问题,但这看起来根本没有任何影响。怪异。

我认为我已经进行了实验,并且我推断如果问题是泄漏了IsFrozen = true那么我想知道是否将它作为VisualBrush弄乱了对象引用,所以我改了它到拥有&#34;拥有&#34;对象,如:

StaticResource

这解决了这个问题!我仍然不知道为什么 - 我想知道它是否是WPF中的一个错误?

在相关的说明中,我意识到使用 <DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Rectangle Fill="{Binding Foreground, ElementName=myDataGrid}" Width="14" Height="14" Margin="4" Visibility="{Binding IconVisibility}" > <VisualBrush Stretch="Uniform" Visual="{StaticResource iconBrush}" /> </Rectangle> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> 是过度的,因为我只渲染一个简单的VisualBrush - Path是昂贵的,因为它渲染了一个整体WPF视图 - 我还从其他文档中了解到VisualBrush本身对于渲染简单形状本身并不是必需的,因为它本身是一个完整的PathUIElement - 它们更重& #34;类型。

我更改了代码,将路径存储在FrameworkElement静态资源中的PathGeometry值中,该资源已加载到GeometryDrawing中:

DrawingBrush

这样做也会影响内存的使用,并希望提高性能。

在您的项目中,我发现您并未将路径信息用作资源,但适用相同的技术:将路径加载到<GeometryDrawing x:Key="iconDrawing" Brush="Black" Geometry="..." /> <Rectangle Fill="{Binding Foreground, ElementName=myDataGrid}" Width="14" Height="14" Margin="4" Visibility="{Binding IconVisibility}" OpacityMask="{StaticResource iconBrush}" > <DrawingBrush Stretch="Uniform" Drawing="{StaticResource iconDrawing}" /> </Rectangle> (或更确切地说,PathGeometry对象中,更快,并且用于不可变几何)并将其设置为StreamGeometry的{​​{1}}。