【问题标题】:Create control asynchronous code behind wpf在 wpf 后面创建控件异步代码
【发布时间】:2019-06-25 16:44:39
【问题描述】:

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

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

但是当图像数量变大(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();
}

【问题讨论】:

标签: c# wpf asynchronous async-await


【解决方案1】:

这是 xaml 中的一个替代方案:

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

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

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

【讨论】:

    【解决方案2】:

    try{}catch() 放入循环体并检查,你肯定会在那里接受。

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

    Image 必须在 GUI 线程上创建。由于您使用Task.Run,因此您从 GUI 线程转到 .NET 线程池。异常必须在 Image 创建时出现。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-18
      • 1970-01-01
      • 2012-12-15
      • 2011-11-19
      相关资源
      最近更新 更多