为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
慕神8447489 2022-01-15 19:37:19
我的 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 有关?
查看完整描述

2 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

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

并删除 FileToBitmapImage。


查看完整回答
反对 回复 2022-01-15
?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

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


我尝试了对绑定等的各种修改,最后只有通过代码和 Source 属性集创建 Image 控件才起作用,然后 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;

        }

    }


查看完整回答
反对 回复 2022-01-15
  • 2 回答
  • 0 关注
  • 214 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信