WinRT - UI虚拟化加载图像异步阻止UI线程

时间:2013-11-13 01:15:53

标签: c# image winrt-xaml virtualization winrt-async

我的图像加载阻塞了UI线程时出现问题,因此我的网格视图在我的Windows应用商店中没有响应。

我想要做的是使gridview中的图像在我的视图模型中绑定到图像属性。 image属性的值由async方法设置。当app启动时,它会加载所有对象,但不会加载实际的图像数据。当UI虚拟化开始并且通过绑定到xaml中的图像控件的图像属性请求图像数据时,将加载图像数据。

所有这些都是在一个可观察的集合中完成的。

以下是一些代码:

    private ImageSource _image = null;
    private String _imagePath = null;
    public ImageSource Image
    {
        get
        {
            SetImageFromStorageFile().ContinueWith(OnAsyncFail, TaskContinuationOptions.OnlyOnFaulted);
            return this._image;
        }
    }

    private async Task SetImageFromStorageFile()
    {
        this.IsLoading = true;
        if (this._image == null && this._imagePath != null)
        {
                this._image = await BitmapLoader.GetPreviewImageFromStorageFile(this.StorageFile); //getting the actual data here
                this.OnPropertyChanged("Image");
        }
        this.IsLoading = false;
    }

除了UI在访问图像数据时没有响应时,这一切都正常。

正如您所看到的,我正在从属性调用异步方法,我只是重用我从其他地方调用的代码。当从其他地方调用时,我可以使用等待,并且UI是响应的。问题是,当使用gridviews UI虚拟化时,我不知道如何在不阻塞UI的情况下运行此异步方法,因为属性不可能运行异步(据我所知)。

所以我只想让gridview运行这个属性(或方法)async而不是sync,但不知道怎么做。

请帮助:)

2 个答案:

答案 0 :(得分:1)

private ImageSource _image = null;
private String _imagePath = null;
public ImageSource Image
{
    get
    {
        if (_image != null)
          return _image;
        if (_imagePath != null && !IsLoading)
          SetImageFromStorageFile();
        return null;
    }
}

private async void SetImageFromStorageFile()
{
    if (this.IsLoading || this._image != null || this._imagePath == null)
      return;
    this.IsLoading = true;
    try
    {
      this._image = await BitmapLoader.GetPreviewImageFromStorageFile(this.StorageFile); //getting the actual data here
      this.IsLoading = false;
      this.OnPropertyChanged("Image");
    }
    catch 
    {
      OnAsyncFail();
    }
}

答案 1 :(得分:0)

无论您选择何种策略,都需要先返回一些内容并稍后填写。这是一个在vanilla WinRT页面中测试过的样本;您可以将其复制到名为Image的{​​{1}}和名为image的{​​{1}}的网页上进行复制。这可以放在TextBlock或其他合适的位置。

status

我“返回”的东西是OnNavigatedTo,它是BitmapImage imgsrc = new BitmapImage(); Task.Run(async () => { await Task.Delay(10000); await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new Windows.UI.Core.DispatchedHandler(() => { imgsrc.UriSource = new Uri("http://www.gratuit-en-ligne.com/telecharger-gratuit-en-ligne/telecharger-image-wallpaper-gratuit/image-wallpaper-animaux/img/images/image-wallpaper-animaux-autruche.jpg"); })); }); image.Source = imgsrc; status.Text = "Done"; 的子类,所以它接近你想要使用的东西。 BitmapImage只是为了在启动和图像填充之间引入明显的延迟,这样您就可以看到状态文本在图像加载之前设置好了。

要使您的样本能够正常运行,您需要在属性中创建(或访问)ImageSource并立即返回,而不必等待它被填充。然后,您开始一个分配实际源数据的后台任务。

实际的因果关系链可能与我在此处显示的不同。例如,您可以从预先创建的集合中访问ImageSource。这将允许您在调用属性之前开始加载图像。但听起来这将是一个让你朝着正确的方向前进的开始。