2014-11-12 2 views
1

Я хотел бы использовать CollectionView элементов в представлении для обновления в реальном времени на основе удаленного XML-файла.Параллельная обработка цикла и обновление пользовательского интерфейса для больших данных

Я использую ObservableCollection, потому что это быстро. У меня есть большой список 25000 записей и иметь другой код, который будет выполняться в каждом параллельном потоке, который должен занять 1 секунду для каждого, следовательно, почему я выбрал параллельно

ServerList.cs

[Serializable] 
public class ServerList 
{ 
    [Serializable] 
    public class ServerList 
    { 
     public List<Server> Servers { get; set; } 
    } 

    [Serializable] 
    public class Server 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
     public int Phone { get; set; } 
     [XmlIgnore] 
     public string FullName { get; set; } 
    } 
} 

ListViewModel. CS

// constructors 
public ServerList.Server ServerListViewItem; 
private ObservableCollection<ServerList.Server> serverListViewItem; 
public ObservableCollection<ServerList> ServerListView 
{ 
    get 
    { 
     return serverListView; 
    } 
    set 
    { 
     this.serverListView = value; 
     this.RaisePropertyChanged("serverListView"); 
    } 
} 
public ServerList serverList { get; set; } 

// load list of servers from XML and parse into collection 
this.serverList = new ServerList(); 
this.ServerListView = new ListCollectionView(new List<ServerList>()); 
XmlDocument xmlFetch = new XmlDocument(); 
xmlFetch.LoadXml(new WebClient().DownloadString("http://domain.com/pathto.xml")); 
XmlNode xmlNode = xmlFetch; 
XmlReader xmlReader = new XmlNodeReader(xmlNode); 
XmlSerializer mySerializer = new XmlSerializer(typeof(ServerList)); 
this.serverList = (ServerList)mySerializer.Deserialize(xmlReader); 

// parallel method should update UI as results are finished 
private void LoadAll() 
{ 
    Parallel.ForEach(
    this.serverList, 
    new ParallelOptions { MaxDegreeOfParallelism = 25 }, 
    row => 
     { 
      this.ServerListViewItem = new ServerList.Server(); 
      string fullName = row.FirstName + " " + row.LastName; 
      this.ServerListViewItem.FullName = fullName; 
      this.ServerListViewItem.FirstName = FirstName; 
      this.ServerListViewItem.LastName = LastName; 
      this.ServerListViewItem.Phone = Phone; 
      ServerListView.Add(ServerListViewItem); // problematic! 
     } 
    ); 
} 

// allow usage of the UI while parallel thread is running 
Thread ParallelProcessThread = new Thread(this.LoadAll); 
ParallelProcessThread.Start(); 

List.xaml

<UserControl.Resources> 
    <Style x:Key="lvStyle" TargetType="{x:Type ListView}"> 
     <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/> 
     <Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling"/> 
     <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="True"/> 
     <Setter Property="ListView.ItemsSource" Value="{Binding Path=ServerListView}"/> 
     <Setter Property="BorderThickness" Value="0"/> 
     <Setter Property="Background" Value="#202020" /> 
     <Setter Property="ListView.View"> 
      <Setter.Value> 
       <GridView AllowsColumnReorder="False"> 
        <GridViewColumn Header="FullName" Width="150"> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> 
           <TextBlock Text="{Binding FullName}"/> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 
        <GridViewColumn Header="FirstName" Width="150"> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> 
           <TextBlock Text="{Binding FirstName}"/> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 
        <GridViewColumn Header="LastName" Width="150"> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> 
           <TextBlock Text="{Binding LastName}"/> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 
        <GridViewColumn Header="Phone" Width="Auto"> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> 
           <TextBlock Text="{Binding Phone}"/> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 
       </GridView> 
      </Setter.Value> 
     </Setter> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding IsLoading}" Value="True"> 
       <Setter Property="ListView.Cursor" Value="Wait"/> 
       <Setter Property="ListView.Background" Value="LightGray"/> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</UserControl.Resources> 

.. звонок в List.xam л

<ListView Style="{DynamicResource lvStyle}" /> 

Я получаю эту ошибку:

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

ответ

1

2 вещи:

  1. Ошибка вы получаете, потому что рабочий поток (не UI нить) не может обновить пользовательский интерфейс , Для обновления пользовательского интерфейса используйте диспетчер. См. Using the C# Dispatcher.
  2. Сценарий и код, который вы упомянули, я не думаю, что вы получаете от него какую-либо выгоду. Код в вашем многопоточном разделе устанавливает только свойства и не выполняет какую-либо тяжелую работу с вычислением или фоном. Поскольку в конечном итоге для обновления пользовательского интерфейса вам придется использовать диспетчер для ServerListView.Add(ServerListViewItem);, то, как он написан, производительность, скорее всего, пострадает. Просто удалите параллель и, если вы действительно хотите сделать ее быстрой, сделайте выборку из удаленной части xml быстро, например. выбор одной записи (или партии записей) за раз.

PS: Не может оставлять комментарии в связи с ограничением на символ.

Смежные вопросы