我正在为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线程在知道我异步运行所有IO操作的情况下阻塞了6秒钟?如何修复这个问题,使UI线程不会被阻塞?
下面是我调用该方法的方式:
private async Task Init()
{
PictureList = await LoadPicturesAsync();
}
//constructor
public MainVewModel(){
Init();
}发布于 2016-03-13 02:09:43
为什么会发生这种情况?
因为您正在尝试并发运行如此多的线程,因为您正在使用list的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返回一个任务,因此您需要注意,在构造完成时可能不会设置PictureList属性/字段,因此如果您试图在实例化后立即访问它,则可能会面临NullReferenceException。
MainViewModel viewModel = new MainViewModel();
var pics = viewModel.PictureList;
var count = pics.Count; // High chance of NullReferenceException为了避免这种情况,您可以考虑为视图模型定义一个静态CreateAsync方法。更多信息可以在here上找到。
https://stackoverflow.com/questions/35960012
复制相似问题