Memory leaks WPF-带有不透明掩码/可视笔刷的边框:内存泄漏
关于我的应用程序的简要说明: 我正在开发的应用程序就是这样一个贺卡设计师。想象一下,其中有一个背景图像和无限数量的“层”(特别是图片),这些层位于背景之上,可以移动、调整大小、前后移动,等等 也可以在这些层上应用特定的形状,如星形、椭圆形等。。卡片制作完成后,可以将其保存到jpeg文件中 问题 一切正常,但我检测到,当一个形状应用于一个层时,会产生内存泄漏 以下是每层用户控件的代码: 参数“MyMask.Data”是一个XAML路径(即我正在应用的形状),我从包含不同形状的文本文件中手动加载该路径 因此,原则是,如果我将边界命名为*im\u the \u problem*,则不会释放内存。如果我评论*我就是问题所在*(因此我将只使用没有形状的矩形层/图片),一切都像一个魅力,没有内存泄漏 问题应该在OpacityMask+VisualBrush中 我做错什么了吗? 还是存在已知的问题?有没有一种方法可以以不同的方式进行相同的操作(将形状应用于图片…)Memory leaks WPF-带有不透明掩码/可视笔刷的边框:内存泄漏,memory-leaks,binding,visualbrush,opacitymask,Memory Leaks,Binding,Visualbrush,Opacitymask,关于我的应用程序的简要说明: 我正在开发的应用程序就是这样一个贺卡设计师。想象一下,其中有一个背景图像和无限数量的“层”(特别是图片),这些层位于背景之上,可以移动、调整大小、前后移动,等等 也可以在这些层上应用特定的形状,如星形、椭圆形等。。卡片制作完成后,可以将其保存到jpeg文件中 问题 一切正常,但我检测到,当一个形状应用于一个层时,会产生内存泄漏 以下是每层用户控件的代码: 参数“MyMask.Data”是一个XAML路径(即我正在应用的形状),我从包含不同形状的文本文件中手动加载该路
谢谢 您可以尝试将MyMask.Data绑定到实际的Path.Data,并将Path.Fill设置为从图像创建的ImageBrush?您需要冻结VisualBrush;) 我在
DataGrid
的列模板中遇到了这个问题,当时我将
(作为静态资源)使用到VisualBrush
(也是一个静态资源)中,并将其用作矩形的不透明掩码。每当重新加载DataGrid时,矩形
就不会释放对OpacityMask
的VisualBrush
引用,我使用内存探查器工具显示所有VisualBrush
对象都在使用大量内存
我不明白为什么会发生这种情况,也不知道是怎么发生的,但我很高兴我不是一个人(即使我在6.5年后也遇到了同样的问题……)
我的XAML是这样的:
<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>
这解决了问题!我仍然不知道为什么——我想知道这是否是WPF中的一个bug
另一方面,我开始意识到使用VisualBrush
有点过分,因为我只渲染一个简单的Path
-VisualBrush
非常昂贵,因为它可以渲染整个WPF视图-我还从其他文档中了解到,Path
本身对于渲染简单的形状来说是不必要的,因为它本身是一个完整的图形UIElement
和FrameworkElement
——它们是“较重”的类型
我更改了代码,将路径存储在加载到DrawingBrush
的GeometryDrawing
静态资源中的PathGeometry
值中:
<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
对象中,该对象速度更快,适用于不可变的几何体),并将其设置为DrawingBrush
的绘图
<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>
<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>
<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>