0

読み込まれたデータを 1 つずつ非同期で表示するコントロールを実装したいと考えています。

これまでのところ、 async awaityieldを試しました。async awaitを使用すると、バインド用のデータが収集されている間、UI を使用できます。

yieldを使用すると、データが収集されてコントロールにバインドされるまで UI がブロックされます。

yieldasync/waitの真の動作を組み合わせることは可能ですか?

ありがとう

コードは次のとおりです。

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace WPFComponents
{
    /// <summary>
    /// Interaction logic for WindowAsync.xaml
    /// </summary>
    public partial class WindowAsync
    {
        public WindowAsync()
        {
            InitializeComponent();
        }

        private async void OnWindowLoad(object sender, RoutedEventArgs e)
        {
            ItemListView.ItemsSource = await GetItemsAsync();
            //ItemListView.ItemsSource = GetItems();
        }

        private async Task<ObservableCollection<string>> GetItemsAsync()
        {
            return await Task.Run(() =>
                {
                    ObservableCollection<string> collection = new ObservableCollection<string>();

                    for (int i = 0; i < 10; i++)
                    {
                        string item = string.Format("Current string from {0}.", i);
                        collection.Add(item);
                        Thread.Sleep(500);
                    }
                    return collection;
                });
        }

        private IEnumerable<string> GetItems()
        {
            for (int i = 0; i < 10; i++)
            {
                string item = string.Format("Current string from {0}.", i);
                Thread.Sleep(500);
                yield return item;
            }
        }
    }
}

XAML は次のとおりです。

<Window x:Class="WPFComponents.WindowAsync"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WindowAsync" Height="300" Width="300" Loaded="OnWindowLoad">
    <Grid>
        <ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled" x:Name="ItemListView"
                      SelectionMode="Multiple" UseLayoutRounding="True"
                      IsSynchronizedWithCurrentItem="True" Margin="0,4,4,4"
                      BorderThickness="0"
                      HorizontalContentAlignment="Center"
                      VerticalContentAlignment="Top">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel IsItemsHost="True" VerticalAlignment="Top" />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListView>

    </Grid>
</Window>
4

1 に答える 1

3

収量と非同期/待機の真の動作を組み合わせることは可能ですか?

await完全な結果を返しますが、TAP に組み込まれている進行状況レポートを使用できます。

ここに記事を書きました: The Progress Reporting Pattern in C# 5 async


したがって、次のようにします。

private void OnWindowLoad(object sender, RoutedEventArgs e)
{
  var collection = new ObservableCollection<string>();
  ItemListView.ItemsSource = collection;

  var progress = new Progress<string>();
  progress.ProgressChanged += ( s, item ) =>
    {
      collection.Add( item ); // will be raised on the UI thread
    }
  ;

  Task.Run( () => GetItemsAndReport( progress ) );
}

void GetItemsAndReport( IProgress<string> progress )
{
    foreach ( var item in GetItems() ) progress.Report( item );
}

private IEnumerable<string> GetItems()
{
    for (int i = 0; i < 10; i++)
    {
        string item = string.Format("Current string from {0}.", i);
        Thread.Sleep(500);
        yield return item;
    }
}
于 2013-04-10T11:14:20.073 に答える