我有一个非常简单的WPF应用程序,用于一次在一个图像中预览任何给定文件夹中的图像.您可以将其视为Windows Image Viewer克隆.该应用程序有一个PreviewKeyUp事件,用于加载文件夹中的上一个或下一个图像,如果按下左箭头或右箭头键.
<Grid>
<Image x:Name="CurrentImage" />
</Grid>
private void Window_PreviewKeyUp(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Left:
DecreaseIndex();
break;
case Key.Right:
IncreaseIndex();
break;
}
var currentFile = GetCurrentFile();
CurrentImage.Source = new BitmapImage(new Uri(currentFile));
}
Run Code Online (Sandbox Code Playgroud)
我试图解决的问题是,在加载多个图像直到垃圾收集发生时,存在大量内存膨胀.您可以在我拍摄的应用程序内存使用情况的屏幕截图中看到这一点.在垃圾收集发生之前,它超过300 MB并不罕见.
我尝试在using语句中包装图像,但这不起作用,因为BitmapImage不实现IDisposable.
using (var image = new BitmapImage(new Uri(currentFile)))
{
CurrentImage.Source = image;
}
Run Code Online (Sandbox Code Playgroud)
将多个图像加载到我的应用程序时,我该怎么做才能防止内存膨胀?
调用.Freeze()位图对象,这将其设置为只读状态并释放其上的一些句柄,以防止它获取GC.
您可以做的另一件事是您可以告诉BitmapImage绕过缓存,您看到的内存可以来自缓存.
CurrentImage.Source = new BitmapImage(new Uri(currentFile),
new RequestCachePolicy(RequestCacheLevel.BypassCache));
Run Code Online (Sandbox Code Playgroud)
最后,如果计算机上没有运行大量程序,会给系统带来内存压力.只要它想要GC,就可以等待.net.在GC期间执行GC很慢并降低性能,如果不需要GC,因为没有人请求ram然后它不执行GC.
当您说预览时,您可能不需要完整的图像尺寸。因此,除了调用之外Freeze,您还可以设置BitmapImage的DecodePixelWidth或DecodePixelHeight属性。
我还建议直接从而FileStream不是从加载图像Uri。请注意,的在线文档UriCachePolicy说是
...代表来自HTTP源的图像的缓存策略的值。
因此它可能不适用于本地文件Uris。
为了安全起见,您可以这样做:
var image = new BitmapImage();
using (var stream = new FileStream(currentFile, FileMode.Open, FileAccess.Read))
{
image.BeginInit();
image.DecodePixelWidth = 100;
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = stream;
image.EndInit();
}
image.Freeze();
CurrentImage.Source = image;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
302 次 |
| 最近记录: |