Создать управляющий асинхронный код за wpf - PullRequest
0 голосов
/ 01 февраля 2019

Я создаю приложение для создания фотогалереи и хочу показать картинки по категориям.

В обычном режиме все работает хорошо, и изображения отображаются.

Но когда количество изображений увеличивается (300), программа зависает, и для ее отображения требуется много времени.

Поэтому я хочу использовать асинхронные и отображать изображения.

Я использовал следующий код, но ничего не происходит, и изображения не отображаются

int HandleFileAsync()
{
    AllofItems.ForEachWithIndex((item, idx) =>
    {

        var cv = new CoverViewItem();
        var contentImg = new Image();
        contentImg.Stretch = Stretch.UniformToFill;
        contentImg.Source = new BitmapImage(new Uri(item, UriKind.Absolute));
        var img = new Image();
        img.Source = new BitmapImage(new Uri(item, UriKind.Absolute));

        //-< source >- 
        BitmapImage src = new BitmapImage();
        src.BeginInit();
        src.UriSource = new Uri(item, UriKind.Absolute);
        //< thumbnail > 
        src.DecodePixelWidth = 160;
        src.CacheOption = BitmapCacheOption.OnLoad;
        //</ thumbnail > 

        src.EndInit();
        img.Source = src;
        //-</ source >- 

        img.Stretch = Stretch.Uniform;
        img.Height = 160;

        cv.Header = img;
        cv.Tag = item;
        cv.Content = contentImg;
        cv.Selected += Cv_Selected;
        cv.Deselected += Cv_Deselected;
        Dispatcher.Invoke(() =>
        {
          cover.Items.Add(cv);
        });
    });
    return AllofItems.Count();
}

async void Example()
{
    // This method runs asynchronously.
    int t = await Task.Run(() => HandleFileAsync());
    Console.WriteLine("Compute: " + t);
}

private void Listbox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{

    AllofItems = GetFileList(@"E:\DL\newArtWork\Art\" + listbox.SelectedItem).ToArray();
    cover.Items.Clear();

    Example();
}

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Вот альтернатива, все в xaml:

<ItemsControl ItemsSource="{Binding FilesList}">
   <ItemsControl.ItemTemplate>
      <DataTemplate>
         <Image Source="{Binding IsAsync=True}"/>
      <DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>

Это заставит каждое изображение загружаться в фоновом потоке и отображать его после того, как это будет сделано.Вы можете добавить ValueConverter, чтобы уменьшить изображения, если вы хотите отобразить их много.

Дело в том, что {Binding IsAsync=True} делает всю магию, которая вам нужна, и она все равно будет асинхронной даже с конвертером

0 голосов
/ 01 февраля 2019

Поместите try{}catch() в тело цикла и проверьте, что вы определенно получите там одобрения.

async void не подходит для обработки исключений, это антипаттерн.

Image должны быть созданы в GUI-потоке.Поскольку вы используете Task.Run, вы переходите от GUI-потока к пулу потоков .NET.Исключение должно быть при создании Image.

Загрузка данных в фоновый поток / пул потоков .NET и создание объектов графического интерфейса с помощью Dispatcher.Invoke()

...