我开发了一个应用程序来捕获图像并将其保存到数据库,但我遇到了内存使用问题。在我的域对象上,我有3个属性:
图像 - 字节数组,内容是jpg
RealImageThumb - 转换为BitmapImage并缩小的字节数组,在带有其他缩略图的gridview中显示给用户
RealImage - 没有setter,字节数组转换为位图源,当用户将鼠标悬停在工具提示上时会显示。
我遇到的问题是,如果用户依次悬停在每个图像上,则内存使用量会呈螺旋式上升。我意识到,当用户盘旋位图源生成并且内存未释放时,我尝试给RealImage一个后备属性并将其分配给null但是内存没有被释放(等待垃圾)集电极?)。
编辑:
这是你的意思雷吗?我没有在工具提示中显示任何内容,如下所示,但如果我尝试定义WeakReference<BitmapImage>
,我会得到System.WeakReference没有类型参数错误。
private WeakReference _realImage;
public virtual BitmapImage RealImage
{
get
{
if (_realImage == null || _realImage.Target == null)
{
if (Image == null) return null;
var newBitmapImage = new BitmapImage();
newBitmapImage.BeginInit();
newBitmapImage.CacheOption = BitmapCacheOption.None;
newBitmapImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
newBitmapImage.StreamSource = new MemoryStream(Image);
newBitmapImage.EndInit();
_realImage = new WeakReference(newBitmapImage);
}
return (BitmapImage)_realImage.Target;
}
}
答案 0 :(得分:3)
您需要做三件事:
构建BitmapImage时,请使用StreamSource提供数据。不要使用UriSource或将Uri传递给构造函数,这会导致图像被添加到图像缓存中。
在域对象的RealImage实现中,将WeakReference存储到BitmapImage而不是BitmapImage本身。获取RealImage时,如果WeakReference或WeakReference.Target为null,则创建一个新的BitmapImage和一个新的WeakReference。
使用带有模板切换功能的DataTrigger,只在可见树中包含Image控件时
以下是步骤3所需的模板,包括带有DataTrigger的模板:
<DataTemplate x:Key="EmptyTemplate">
</DataTemplate>
<DataTemplate x:Key="RealImageTemplate">
<Image Source="{Binding RealImage.Target}" Width="300" Height="300" />
</DataTemplate>
<DataTemplate x:Key="RealImageWhenVisible">
<!-- Use EmptyTemplate when I am not visible -->
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource EmptyTemplate}"/>
<!-- Switch to RealImageTemplate when I am visible -->
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsVisible, RelativeSource={RelativeSource Self}}"
Value="True">
<Setter TargetName="Presenter"
Property="ContentPresenter.ContentTemplate"
Value="{StaticResource RealImageTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
现在您可以像这样定义工具提示:
<Rectangle Width="40" Height="40" Fill="Blue">
<Rectangle.ToolTip>
<ContentPresenter Content="{Binding}"
ContentTemplate="{StaticResource RealImageWhenVisible}" />
</Rectangle.ToolTip>
</Rectangle>
工作原理:彼此之间有两个ContentPresenters:
您需要执行此操作的原因是,工具提示可能会尝试通过在弹出窗口显示后不处置它来优化性能。
<强>更新强>
您为RealImage发布的代码应该可以工作,而且几乎正是我的想法。我意识到今天早上只要没有指定SourceUri就没有必要设置BitmapCacheOption或BitmapCreateOption。我已经更新了我的答案以反映这一点,并澄清了WeakReference的事情。我还纠正了模板中的一个错误:当我应该绑定到“RealImage.Target”时,我绑定到“RealImage”。