2

I'm creating a photo gallery app and I want to show pictures by category.

In normal mode, everything works well and the images are displayed.

But when the number of images gets bigger (300), the program will hang and it takes a long time to show.

So I want to use asynchronous and display images.

I used the following code but nothing happens and the images are not displayed

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();
}
1

2 Answers 2

2

Here is an alternative, whole thing in xaml:

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

This will make each image load in background thread and display it after it's done. You can add a ValueConverter to scale down the images if you want to display a lot of them.

Point is, {Binding IsAsync=True} does all the magic you need and it will be still async even with a converter

Sign up to request clarification or add additional context in comments.

Comments

0

Put a try{}catch() to the loop's body and check, you will definitely have acceptions there.

async void is not good for exception handling, it's an antipattern.

Image have to be created on the GUI-thread. Since you use Task.Run you go from GUI-thread to the .NET thread pool. Exception must be on Image creation.

Load the data in a background thread/.NET thread pool and do GUI objects creation with Dispatcher.Invoke()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.