2013-11-13 3 views
2

У меня возникают проблемы с загрузкой моего изображения, блокируя поток пользовательского интерфейса, поэтому мой gridview не реагирует на мое приложение для хранения Windows.WinRT - Виртуализация пользовательского интерфейса Загрузка изображений async blocking UI Thread

Что я пытаюсь сделать для изображений в gridview иметь привязку к свойству изображения в моей модели просмотра. Значение свойства изображения устанавливается с помощью метода async. Когда приложение запускается, он загружает все объекты, но не фактические данные изображения. Данные изображения загружаются, когда виртуализация пользовательского интерфейса запускается и запрашивает данные изображения через свойство изображения, связанное с элементом управления изображением в 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; 
    } 

Это все работает нормально, за исключением того, что пользовательский интерфейс перестает отвечать на запросы при доступе к данным изображения.

Как вы можете видеть, я вызываю метод async из свойства, я просто повторно использую код, который я вызываю из других мест. При вызове из других мест я могу использовать ожидание, и пользовательский интерфейс реагирует. Проблема в том, что при использовании виртуализации пользовательских интерфейсов gridviews я не знаю, как запустить этот асинхронный метод без блокировки пользовательского интерфейса, поскольку свойства не могут запускаться async (насколько я знаю).

Поэтому я просто хочу, чтобы gridview запускал эту функцию (или метод) вместо синхронизации, но не знаю, как это сделать.

Пожалуйста, помогите :)

+0

После того, как я разорвал волосы, я решил посмотреть, была ли проблема с сеткой. И если я удалил с помощью группировки и просто использовал простую сетку, он работал так, как я ожидал. Поэтому у меня нет ответа на мой вопрос, но обходной путь. Нехорошо. – madmarten

ответ

0

Независимо от стратегии, вы выбираете, что вам нужно, чтобы вернуть то, что первый и заполнить его позже. Это образец, который был протестирован на ванильной странице WinRT; вы можете дублировать его, отбросив его на страницу с Image с именем image и 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, так что это близко к тому, что вы хотите использовать. Task.Delay() - это просто ввести очевидное отставание между загрузкой и населением изображения, чтобы вы могли видеть, что текст состояния задан задолго до загрузки изображения.

Чтобы сделать это с вашим образцом, вам нужно будет создать (или получить) ImageSource в своей собственности и немедленно вернуть его, не дожидаясь его заполнения. Затем вы начинаете фоновую задачу, которая назначает фактические исходные данные.

Фактическая цепочка причинности может отличаться от того, что я показываю здесь. Например, вы можете получить доступ к ImageSources из предварительно созданной их коллекции. Это позволит вам начать загрузку изображений до того, как свойство когда-либо будет вызвано. Но похоже, что это станет началом для того, чтобы вы двигались в правильном направлении.

+0

К сожалению, это не помогло в моем случае, но оно должно быть :) – madmarten

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

Я бы порекомендовал вам изменить свою подпись на VOID вместо TASK. –

Смежные вопросы