【发布时间】:2018-09-13 11:11:54
【问题描述】:
我的 WPF MVVM 应用程序通过 Webclient.DownloadFileAsync(url, fileLocation) 从给定的 URL 异步加载图像。该过程顺利进行,下载图片时根本没有冻结。但是当我将图像文件呈现给用户时会出现问题 - 应用程序变得无响应。
文件下载后,我将图像文件分配给BitmapImage:
public async void LoadFileToBitmapImage(string filePath)
{
_isDownloading = false;
await FileToBitmapImage(filePath);
}
public Task FileToBitmapImage(string filePath)
{
return Task.Run(() =>
{
var executableLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var imageLocation = Path.Combine(executableLocation, filePath);
var bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(imageLocation);
bi.EndInit();
bi.Freeze();
Image = bi;
});
}
Image.cs:
private BitmapImage _image;
public BitmapImage Image
{
get => _image;
set
{
_image = value;
NotifyOfPropertyChange("Image");
}
}
XAML 图像绑定:
<Image Source="{Binding Image, IsAsync=True}" Margin="3"/>
下载图像并将其呈现给用户时会出现问题。图像越大,将图像呈现给用户所需的时间就越长,应用程序无响应的时间也就越长。
当应用程序冻结以检查线程并获取the following info 时,我尝试单击暂停,但不幸的是它没有为我提供任何信息。
任何帮助将不胜感激!
编辑
值得注意的是,应用程序变得无响应在 PropertyChanged 事件引发之后,而不是之前。也许这与向 UI 渲染图像有关?
【问题讨论】:
-
您不能在调度程序线程以外的任何线程上分配图像。 UI因此冻结。您需要将任务编组回调度员。
-
@Peregrine 我尝试了您的解决方案,但没有运气。使用 5000x5000 和 20000x10000 图片时仍会冻结。值得注意的是,在引发 PropertyChanged 事件之后,我的代码和你的代码都会冻结,而不是之前。也许这与将图像渲染到 UI 有关?
-
假设您的显示器不支持 20000x10000 分辨率,我建议您为每个图像生成一个适当大小的缩略图版本以供此类使用,否则图像控件正在为缩放。
-
@Peregrine 好主意。将尝试将其调整到足够的大小,然后加载到 ui。
-
缩小位图当然是值得做的事情。但就您的实际问题而言,您应该知道位图在第一次需要之前实际上不会加载到对象中,除非您更改缓存设置。见标记重复。如果这不能解决问题,请发布一个新问题,其中您提供了一个很好的minimal reproducible example,它实际上重现了问题。
标签: c# wpf multithreading mvvm