UI 在图像控件加载 BitmapImage 时冻结

我的 WPF MVVM 应用程序通过Webclient.DownloadFileAsync(url, fileLocation). 该过程顺利进行,下载图片时根本没有冻结。但是当我将图像文件呈现给用户时会出现问题 - 应用程序变得无响应。


下载文件后,我将图像文件分配给 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;

        });

    }

图片.cs:


private BitmapImage _image;

public BitmapImage Image

    {

        get => _image;

        set

        {

            _image = value;

            NotifyOfPropertyChange("Image");

        }

    }

XAML 图像绑定:


<Image Source="{Binding Image, IsAsync=True}" Margin="3"/>

下载图像并将其呈现给用户时会出现问题。图像越大,向用户呈现图像所需的时间越多,应用程序无响应的时间就越长。


当应用程序冻结以检查线程并获取以下信息时,我尝试单击暂停,不幸的是它没有为我提供任何信息。


任何帮助都感激不尽!


编辑


值得注意的是,在引发 PropertyChanged 事件之后,应用程序变得无响应,而不是之前。也许这与将图像渲染到 UI 有关?


慕神8447489
浏览 215回答 2
2回答

杨魅力

首先,如果你保存图像,直接将绑定更改为字符串/uri,没有 BitmapImage,不需要创建它,Wpf 为你处理 public BitmapImage Image ===> public Uri Image并删除 FileToBitmapImage。

鸿蒙传说

我花了几天的时间来找到解决这个问题的简单方法。我需要在不冻结 UI 的情况下以高质量显示一百多张图像。我尝试了对绑定等的各种修改,最后只有通过代码和 Source 属性集创建 Image 控件才起作用,然后 Image 出现在界面元素树中。在 XAML 中只有空的 ContentControl:&nbsp; &nbsp; <ContentControl x:Name="ImageContent"/>在代码中:&nbsp; &nbsp; static readonly ConcurrentExclusiveSchedulerPair _pair = new&nbsp; ConcurrentExclusiveSchedulerPair();&nbsp; &nbsp; // Works for very big images&nbsp; &nbsp; public void LoadImage(Uri imageUri)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var image = new System.Windows.Controls.Image(); // On UI thread&nbsp; &nbsp; &nbsp; &nbsp; RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.HighQuality);&nbsp; &nbsp; &nbsp; &nbsp; Task.Factory.StartNew(() =>&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var source = new BitmapImage(imageUri); // load ImageSource&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dispatcher.RunOnMainThread(() =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; image.Source = source; // Set source while not in UI&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Add image in UI tree&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ImageContent.Content = image; // ImageContent is empty ContentControl&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ImageContent.InvalidateVisual();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; }, default, TaskCreationOptions.LongRunning, _pair.ExclusiveScheduler);&nbsp; &nbsp; }使用 CacheOption OnLoad 加载图像效果更好。&nbsp; &nbsp; public static ImageSource BitmapFromUri(Uri source)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (source == null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new BitmapImage(source);&nbsp; &nbsp; &nbsp; &nbsp; using (var fs = new FileStream(source.LocalPath, FileMode.Open))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var bitmap = new BitmapImage();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bitmap.BeginInit();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bitmap.StreamSource = fs;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bitmap.CacheOption = BitmapCacheOption.OnLoad;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bitmap.EndInit();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bitmap.Freeze();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return bitmap;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP