【问题标题】:UI freezes at the moment Image control loads BitmapImage [duplicate]UI 在图像控件加载 BitmapImage 时冻结 [重复]
【发布时间】: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


【解决方案1】:

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

并删除 FileToBitmapImage。

【讨论】:

  • 感谢您指出这一点,我已经解决了。虽然问题仍然存在。
  • 你的图片有多大?
  • 我尝试使用不同尺寸的图像。从 2048x1024 到 20000x10000。 2k 图像的延迟仍然存在,但它太少了,无法意识到。当文件非常大时,情况会发生变化。
  • 太大了,没有办法...或者必须像这里一样先加载它们-github.com/TheCamel/CBR/blob/master/CBR.Core/Models/Book/…-然后将您的属性改回位图图像。它只是一个图像查看器吗?还是更复杂的?
【解决方案2】:

我花了几天时间来寻找解决这个问题的简单方法。我需要在不冻结 UI 的情况下以高质量显示一百多张图像。

我尝试了各种绑定等修改,最后只有通过代码创建 Image 控件和 Source 属性集在 Image 出现在界面元素树中之前起作用。

在 XAML 中只有空的 ContentControl:

    <ContentControl x:Name="ImageContent"/>

在代码中:

    static readonly ConcurrentExclusiveSchedulerPair _pair = new  ConcurrentExclusiveSchedulerPair();

    // Works for very big images
    public void LoadImage(Uri imageUri)
    {
        var image = new System.Windows.Controls.Image(); // On UI thread
        RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.HighQuality);

        Task.Factory.StartNew(() =>
        {
            var source = new BitmapImage(imageUri); // load ImageSource

            Dispatcher.RunOnMainThread(() =>
            {
                image.Source = source; // Set source while not in UI

                // Add image in UI tree
                ImageContent.Content = image; // ImageContent is empty ContentControl
                ImageContent.InvalidateVisual();
            });
        }, default, TaskCreationOptions.LongRunning, _pair.ExclusiveScheduler);
    }

使用 CacheOption OnLoad 加载图像效果更好。

    public static ImageSource BitmapFromUri(Uri source)
    {
        if (source == null)
            return new BitmapImage(source);

        using (var fs = new FileStream(source.LocalPath, FileMode.Open))
        {
            var bitmap = new BitmapImage();
            bitmap.BeginInit();
            bitmap.StreamSource = fs;
            bitmap.CacheOption = BitmapCacheOption.OnLoad;
            bitmap.EndInit();
            bitmap.Freeze();
            return bitmap;
        }
    }

【讨论】:

  • “异步加载大型 BitmapImage”不是答案。该错误与加载无关,而是在 wpf 中显示。
猜你喜欢
  • 2013-10-22
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
  • 2018-11-23
  • 1970-01-01
  • 2014-07-29
  • 1970-01-01
  • 2020-02-26
相关资源
最近更新 更多