.net - 异步加载大 BitmapImage

标签 .net wpf async-await

我正在尝试将非常大的图像(大约 16000x7000 像素)加载到 Material 中,并且我尝试异步加载它。我的第一次尝试是创建一个加载 BitmapImage 的任务,然后将其使用到 Material 中:

var bmp = await System.Threading.Tasks.Task.Run(() =>
{
    BitmapImage img = new BitmapImage(new Uri(path));
    ImageBrush brush = new ImageBrush(img);
    var material = new System.Windows.Media.Media3D.DiffuseMaterial(brush);
    material.Freeze();
    return material;
});
BackMaterial = bmp;

但是我发现,直到显示 Material 之前,图像都没有加载并扩展到内存中(如果我直接使用 ImageBrush 也是一样的)。

我试图避免这种情况,因为它会卡住我的用户界面,但我还没有找到强制位图加载和解码的正确方法。如果我添加 WriteableBitmap,图片的加载将在任务内执行,但随后我将使用的内存量加倍:

var bmp = await System.Threading.Tasks.Task.Run(() =>
{
    BitmapImage img = new BitmapImage(new Uri(path));
    WriteableBitmap wbmp = new WriteableBitmap(img);
    ImageBrush brush = new ImageBrush(wbmp);
    var material = new System.Windows.Media.Media3D.DiffuseMaterial(brush);
    material.Freeze();
    return material;
});
BackMaterial = bmp;

有什么方法可以强制加载而不将其加倍到内存中。我也尝试用解码器加载它,但我也加载到内存中两次:

var decoder = BitmapDecoder.Create(new Uri(path), BitmapCreateOptions.PreservePixelFormat,
     BitmapCacheOption.None);
var frame = decoder.Frames[0];
int stride = frame.PixelWidth * frame.Format.BitsPerPixel / 8;
byte[] lines = new byte[frame.PixelHeight * stride];
frame.CopyPixels(lines, stride, 0);
var img = BitmapImage.Create(
    frame.PixelWidth, frame.PixelHeight, frame.DpiX, frame.DpiY, frame.Format,
    frame.Palette, lines, stride);
frame = null;
lines = null;

谢谢!

最佳答案

我不确定这个异步场景,但您通常会设置 BitmapCacheOption.OnLoad强制立即缓存到内存:

var bmp = await System.Threading.Tasks.Task.Run(() => 
{ 
    BitmapImage img = new BitmapImage(); 
    img.BeginInit(); 
    img.CacheOption = BitmapCacheOption.OnLoad; 
    img.UriSource = new Uri(path); 
    img.EndInit(); 
    ImageBrush brush = new ImageBrush(img); 
    ...
}

关于.net - 异步加载大 BitmapImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12825233/

相关文章:

c# - 卸载 SQL Server Express 2005,然后在 C# ClickOnce Winform App 中安装 SQL Server 2008 R2 Express

.net - 如何使用ConcurrentDictionary,INotifyCollectionChanged,INotifyPropertyChanged创建自定义可观察集合

c# - botbuilder 不等待来自 HTTP 响应的响应(使用 Restsharp)

javascript - 使用异步函数调用创建新的 Promise 是不好的做法吗?

c# - 如何从异步方法向调用者抛出异常?

.net - 将 IIS 网站应用程序设置为使用应用程序池身份进行匿名身份验证(通过代码)

c# - 如何为 DataGridComboBoxColumn WPF 绑定(bind)数组

wpf - 如何通过多线程将 DataRow 添加到 Viewmodel 中的 DataTable

c# - 如何将 WPF TextBlock 文本绑定(bind)到不同的属性?

c# - async & await - 如何等到所有任务完成?