在WPF之后创建控件异步代码

时间:2019-02-01 06:14:28

标签: c# wpf asynchronous async-await

我正在创建一个相册应用,我想按类别显示图片。

在正常模式下,一切正常,并显示图像。

但是,当图像数量变大(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 :(得分:2)

这是xaml中的另一种选择:

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

这将使每个图像都在后台线程中加载并在完成后显示。如果要显示很多图像,可以添加ValueConverter来按比例缩小图像。

重点是,{Binding IsAsync=True}完成了您需要的所有魔术,即使使用转换器,它仍然是异步的

答案 1 :(得分:0)

在循环的主体中放置try{}catch()并检查,您肯定会在其中接受。

async void不适用于异常处理,它是一种反模式。

Image必须在GUI线程上创建。由于使用Task.Run,因此从GUI线程转到.NET线程池。 Image创建时必须例外。

将数据加载到后台线程/.NET线程池中,并使用Dispatcher.Invoke()创建GUI对象

相关问题