我正在为UWP开发一款应用。
我需要加载一个包含大约700张小图片的文件夹。这是我用来将图片加载到内存中的方法:
private async Task<ObservableCollection<ImageSource>> LoadPicturesAsync()
{
var pictureList = new ObservableCollection<ImageSource> { };
pictureFiles.ForEach(async file =>
{
var img = new BitmapImage();
pictureList.Add(img);
var stream = await file.OpenReadAsync();
await img.SetSourceAsync(stream);
});
return pictureList;
}
当我的视图模型的构造函数调用此方法时,视图似乎被阻止(无响应)大约6秒。
这很奇怪,因为所有IO操作都是异步完成的,并且UI线程中唯一运行的是在foreach循环中创建BitmapImage对象。这是如此之快,它不应该阻止UI线程。
我的问题是:为什么UI线程阻塞了6秒,因为我知道我是异步运行所有IO操作的?以及如何修复这个UI线程没有被阻止?
这就是我称之为该方法的方式:
private async Task Init()
{
PictureList = await LoadPicturesAsync();
}
//constructor
public MainVewModel(){
Init();
}
答案 0 :(得分:0)
为什么会这样?
因为您正在尝试同时运行这么多线程,因为您正在使用列表的ForEach方法并将异步操作传递给它。用for-each替换ForEach,你就没事了。
private async Task<ObservableCollection<ImageSource>> LoadPicturesAsync() {
foreach (var file in pictureFiles) {
var stream = await file.OpenReadAsync();
var image = new BitmapImage();
await image.SetSourceAsync(stream);
pictureList.Add(image );
}
}
private async Task Init() {
PictureList = await LoadPicturesAsync();
}
毕竟,我看到你在视图模型中调用了Init方法:
//constructor
public MainVewModel(){
Init();
}
由于Init返回一个Task,你需要知道在构造完成时可能没有设置PictureList属性/字段,所以如果你在实例化后立即尝试访问它,你可能会遇到NullReferenceException。
MainViewModel viewModel = new MainViewModel();
var pics = viewModel.PictureList;
var count = pics.Count; // High chance of NullReferenceException
为了避免这种情况,您可以考虑为视图模型定义静态CreateAsync方法。可以找到更多信息here。