【发布时间】:2022-01-24 03:09:57
【问题描述】:
我一直在寻找将图像绑定/加载到列表的性能影响降到最低的方法。
我尝试了一些人们在网上建议的不同选项,例如:
或使用单独的线程将图像列表加载到 ImageSource 中,然后绑定到列表视图
和/或与标记为异步的主要源的优先级绑定(当我单独使用这种方法时,我没有看到任何改进,tbh)
他们都有一定程度的改进,我最终得到了如下内容: 具有异步加载功能的自定义图像控件
public class AsyncImage : Image
{
private static ImageSource _blank;
private static Random random;
private static ImageSource Blank
{
get
{
if(_blank == null)
{
var bi = new BitmapImage();
bi.BeginInit();
Stream imgStream = File.OpenRead("D:\\...\\blankLoading.png");
bi.StreamSource = imgStream;
bi.EndInit();
bi.Freeze();
_blank = bi;
}
return _blank;
}
}
public string ImageUrl
{
get { return GetValue(ImageUrlProperty).ToString(); }
set
{
SetValue(ImageUrlProperty, value);
LoadImageAsync(value);
}
}
public static readonly DependencyProperty ImageUrlProperty =
DependencyProperty.Register("ImageUrl", typeof(string), typeof(AsyncImage), new UIPropertyMetadata(string.Empty, new PropertyChangedCallback(OnImageUrlChanged)));
private static void OnImageUrlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
AsyncImage control = (AsyncImage)d;
control.ImageUrl = e.NewValue.ToString();
}
private void LoadImageAsync(string url)
{
Image image = new Image();
base.Source = Blank;
ThreadPool.QueueUserWorkItem((r) =>
{
BitmapImage bi = null;
bi = new BitmapImage();
bi.BeginInit();
var bytes = File.ReadAllBytes(url); //i want to make sure data is loaded before assignment
bi.StreamSource = new MemoryStream(bytes);
bi.EndInit();
bi.Freeze(); //makes sure your image can be passed across threads
Console.Write(url);
image.Dispatcher.Invoke(DispatcherPriority.Normal,
(ThreadStart)delegate
{
base.Source = bi; //this is where it actually comes back to UI thread
});
});
}
}
使用这种方法,我可以将 URL 列表或文件路径绑定到列表视图,并且数据绑定将执行得更加流畅......但是,当实际图像是已显示(在最后一行)。当您有一个很好的最后图像列表时,冻结会更加明显。
有没有办法解决这个问题?我想要的是,当图像显示时,UI 仍然可以响应......
【问题讨论】:
-
你是否在这段代码中正确地处理了所有地方的资源?如果碰巧在任何地方留下了未处理的资源,那么这可能会成为临时内存占用,我想这可能会减慢执行速度。只是一个想法。
-
你是对的@BentTranberg,好点。一旦我解决了问题并整理了代码,我就会这样做。在这个阶段不太确定我的代码。
标签: c# wpf image data-binding .net-framework-4.8