471,321 Members | 1,739 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,321 software developers and data experts.

Live update stocks and prices from stocks markets

I've wpf application, where I load large data (into Wpf DataGrid) and handle multiple events per 1-5 seconds..

I have a performance issue with datagrid - rendering takes too long and freezes my app until it's all rendered.

QuestionTester.View.QuestionView:

Expand|Select|Wrap|Line Numbers
  1. <UserControl x:Class="QuestionTester.View.QuestionView"
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  6.              xmlns:local="clr-namespace:QuestionTester.View"
  7.              mc:Ignorable="d"
  8.              xmlns:Converters="clr-namespace:QuestionTester.Converters"
  9.              d:DesignHeight="450" d:DesignWidth="800">
  10.     <UserControl.Resources>
  11.         <Converters:FromDateConverter x:Key="FromDateConv"/>
  12.         <Converters:ToDateConverter x:Key="ToDateConv"/>
  13.         <Converters:ToTimeConverter x:Key="ToTimeConv"/>
  14.     </UserControl.Resources>
  15.     <Grid>
  16.         <Grid.RowDefinitions>
  17.             <RowDefinition Height="20"/>
  18.             <RowDefinition Height="*"/>
  19.         </Grid.RowDefinitions>
  20.         <TextBlock Grid.Row="0" Text="{Binding RecordsCount}"/>
  21.         <DataGrid
  22.             Grid.Row="1"
  23.             ItemsSource="{Binding Models}"
  24.             IsReadOnly="True" 
  25.             AutoGenerateColumns="False" 
  26.             SnapsToDevicePixels="False"
  27.             VirtualizingStackPanel.IsVirtualizing="True"
  28.             VirtualizingStackPanel.VirtualizationMode="Recycling" 
  29.             EnableRowVirtualization="True" 
  30.             MaxWidth="2560" 
  31.             MaxHeight="1600">
  32.             <DataGrid.Columns>
  33.                 <DataGridTemplateColumn Header="CreationTime" ToolTipService.ToolTip="CreationTime">
  34.                     <DataGridTemplateColumn.CellTemplate>
  35.                         <DataTemplate>
  36.                             <StackPanel Margin="4,0,0,0"  FlowDirection="LeftToRight"  VerticalAlignment="Center">
  37.                                 <ToolTipService.ToolTip>
  38.                                     <TextBlock Text="{Binding Path=CreationTime, Converter={StaticResource ToTimeConv}}"/>
  39.                                 </ToolTipService.ToolTip>
  40.                                 <TextBlock HorizontalAlignment="Left" Text="{Binding Path=CreationTime, Converter={StaticResource ToTimeConv}}"/>
  41.                             </StackPanel>
  42.                         </DataTemplate>
  43.                     </DataGridTemplateColumn.CellTemplate>
  44.                 </DataGridTemplateColumn>
  45.                 <DataGridTemplateColumn Header="StartDate" ToolTipService.ToolTip="StartDate">
  46.                     <DataGridTemplateColumn.CellTemplate>
  47.                         <DataTemplate>
  48.                             <StackPanel Margin="4,0,0,0"  FlowDirection="LeftToRight"  VerticalAlignment="Center">
  49.                                 <ToolTipService.ToolTip>
  50.                                     <TextBlock Text="{Binding Path=StartDate, Converter={StaticResource FromDateConv}}"/>
  51.                                 </ToolTipService.ToolTip>
  52.                                 <TextBlock HorizontalAlignment="Left" Text="{Binding Path=StartDate, Converter={StaticResource FromDateConv}}"/>
  53.                             </StackPanel>
  54.                         </DataTemplate>
  55.                     </DataGridTemplateColumn.CellTemplate>
  56.                 </DataGridTemplateColumn>
  57.                 <DataGridTemplateColumn Header="EndDate" ToolTipService.ToolTip="EndDate">
  58.                     <DataGridTemplateColumn.CellTemplate>
  59.                         <DataTemplate>
  60.                             <StackPanel Margin="4,0,0,0"  FlowDirection="LeftToRight"  VerticalAlignment="Center">
  61.                                 <ToolTipService.ToolTip>
  62.                                     <TextBlock Text="{Binding Path=EndDate, Converter={StaticResource ToDateConv}}"/>
  63.                                 </ToolTipService.ToolTip>
  64.                                 <TextBlock HorizontalAlignment="Left" Text="{Binding Path=EndDate, Converter={StaticResource ToDateConv}}"/>
  65.                             </StackPanel>
  66.                         </DataTemplate>
  67.                     </DataGridTemplateColumn.CellTemplate>
  68.                 </DataGridTemplateColumn>
  69.                 <DataGridTextColumn Header="Guid" Binding="{Binding Path=Guid}"/>
  70.                 <DataGridTextColumn Header="Key" Binding="{Binding Path=Key}"/>
  71.                 <DataGridTextColumn Header="Field" Binding="{Binding Path=Field}"/>
  72.                 <DataGridTextColumn Header="Field1" Binding="{Binding Path=Field1}"/>
  73.                 <DataGridTextColumn Header="Field2" Binding="{Binding Path=Field2}"/>
  74.             </DataGrid.Columns>
  75.         </DataGrid>
  76.     </Grid>
  77. </UserControl>
Expand|Select|Wrap|Line Numbers
  1. public partial class QuestionView : UserControl
  2. {
  3.     QuestionViewModel _vm;
  4.     public QuestionView()
  5.     {
  6.         InitializeComponent();
  7.         _vm = new QuestionViewModel(TaskScheduler.FromCurrentSynchronizationContext());
  8.         DataContext = _vm;
  9.     }
  10. }
QuestionModel:

Expand|Select|Wrap|Line Numbers
  1.  public class QuestionModel
  2. {
  3.     public static Random _rand = new Random();
  4.     public DateTime StartDate { get; set; }
  5.     public DateTime EndDate { get; set; }
  6.     public DateTime CreationTime{ get; set; }
  7.     public Guid Guid { get; set; }
  8.     public string Key { get; set; }
  9.     public int Field { get; set; }
  10.     public long Field1 { get; set; }
  11.     public double Field2 { get; set; }
  12.     public QuestionModel(int num)
  13.     {
  14.         Key = $"key_{num}";
  15.         Field = _rand.Next(1000000);
  16.         Field1 = _rand.Next(1000000);
  17.         Field2 = _rand.Next(1000000);
  18.         Guid = Guid.NewGuid();
  19.         CreationTime = DateTime.Now;
  20.         if (num % 2 == 0)
  21.         {
  22.             StartDate = DateTime.Now.AddDays(-1);
  23.             EndDate = DateTime.Now.AddDays(1);
  24.         }
  25.         if (num % 10 == 0)
  26.         {
  27.             StartDate = DateTime.Now.AddDays(-100);
  28.             EndDate = DateTime.Now.AddDays(100);
  29.         }
  30.         else
  31.         {
  32.             StartDate = DateTime.Now;
  33.             EndDate = DateTime.Now;
  34.         }
  35.     }
  36.     public override string ToString()
  37.     {
  38.         return $"CreationTime:{CreationTime}";
  39.     }
  40. }
QuestionViewModel:

Expand|Select|Wrap|Line Numbers
  1. public class QuestionViewModel : NotificationBase, IUpdateTotalItems, IDisposable
  2. {
  3.     const int RAND = 10000000;
  4.     static Random _rand = new Random();
  5.     const int LENGTH = 1000;
  6.     public BulkObservableCollection<QuestionModel> Models { get; }// = new BulkObservableCollection<QuestionModel>();
  7.     TaskScheduler _currentcontext;
  8.     Guid _cancelToken;
  9.     HashSet<Guid> _cancelTokensDict = new HashSet<Guid>();
  10.     DispatcherTimer _dispatcherUpdateTimer;
  11.     Thread _thread;
  12.     public QuestionViewModel(TaskScheduler currentcontext)
  13.     {
  14.         _currentcontext = currentcontext;
  15.         _cancelToken = Guid.NewGuid();
  16.         Models = new BulkObservableCollection<QuestionModel>(_cancelToken, ref _cancelTokensDict, this);
  17.  
  18.         _dispatcherUpdateTimer = new DispatcherTimer(DispatcherPriority.Background);
  19.         _dispatcherUpdateTimer.Interval = TimeSpan.FromMilliseconds(1000);
  20.         _dispatcherUpdateTimer.Tick += _dispatcherUpdateTimer_Tick;
  21.         _dispatcherUpdateTimer.Start();
  22.         QuestionModel[] array = new QuestionModel[LENGTH];
  23.         for (int i = 0; i < LENGTH; i++)
  24.         {
  25.             int indx = _rand.Next(RAND);
  26.             array[i] = new QuestionModel(indx);
  27.         }
  28.         Models.AddRange(array);
  29.         Models.LoadingFinished();
  30.         _thread = new Thread(() =>
  31.         {
  32.             while (!_cancelTokensDict.Contains(_cancelToken))
  33.             {
  34.                 QuestionModel[] arrayThread = new QuestionModel[LENGTH];
  35.                 for (int i = 0; i < LENGTH; i++)
  36.                 {
  37.                     int indx = _rand.Next(RAND);
  38.                     arrayThread[i] = new QuestionModel(indx);
  39.                 }
  40.                 Task.Factory.StartNew(() =>
  41.                 {
  42.                     try
  43.                     {
  44.                         for (int i = 0; i < arrayThread.Length; i++)
  45.                         {
  46.                             Models.Enqueue(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, arrayThread[i], 0));
  47.                         }
  48.                        // Models.AddRange(arrayThread);
  49.                     }
  50.                     catch (Exception)
  51.                     {
  52.                         throw;
  53.                     }
  54.                 }, CancellationToken.None, TaskCreationOptions.None, _currentcontext);
  55.                 Thread.Sleep(1000);
  56.             }
  57.         });
  58.         _thread.IsBackground = true;
  59.         _thread.Start();
  60.     }
  61.  
  62.  
  63.     private int Comparison(QuestionModel a, QuestionModel b)
  64.     {
  65.         if (a == null)
  66.             return 1;
  67.         if (b == null)
  68.             return -1;
  69.         var comprand = b.CreationTime.CompareTo(a.CreationTime);
  70.         return comprand;
  71.     }
  72.  
  73.     private void _dispatcherUpdateTimer_Tick(object sender, EventArgs e)
  74.     {
  75.         if (Models.IsLoading)
  76.             return;
  77.  
  78.         Models.Refresh();
  79.     }
  80.  
  81.     int _recordsCound;
  82.     public int RecordsCount
  83.     {
  84.         get => _recordsCound;
  85.         set
  86.         {
  87.             if (_recordsCound != value)
  88.             {
  89.                 _recordsCound = value;
  90.                 OnPropertyChanged("RecordsCount");
  91.             }
  92.         }
  93.     }
  94.  
  95.     public void UpdateTotalItems(int count)
  96.     {
  97.         RecordsCount = count;
  98.     }
  99.  
  100.     bool _isDisposed = false;
  101.     public void Dispose()
  102.     {
  103.         if (!_isDisposed)
  104.         {
  105.             _isDisposed = true;
  106.             lock (_cancelTokensDict)
  107.             {
  108.                 _cancelTokensDict.Add(_cancelToken);
  109.             }
  110.             if (_thread != null)
  111.             {
  112.                 try
  113.                 {
  114.                     _thread.Join();
  115.                 }
  116.                 catch
  117.                 {
  118.                 }
  119.                 _thread = null;
  120.             }
  121.             if (_dispatcherUpdateTimer != null)
  122.             {
  123.                 _dispatcherUpdateTimer.Stop();
  124.                 _dispatcherUpdateTimer.Tick -= _dispatcherUpdateTimer_Tick;
  125.                 _dispatcherUpdateTimer = null;
  126.             }
  127.         }
  128.     }
  129. }
Converters:

Expand|Select|Wrap|Line Numbers
  1.  public class ToTimeConverter : IValueConverter
  2. {
  3.     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  4.     {
  5.         if (value == null)
  6.             return null;
  7.         DateTime? date = (DateTime)value;
  8.         if (date.HasValue)
  9.         {
  10.             return date.Value.ToString("HH:mm:ss:fff");
  11.         }
  12.         return null;
  13.     }
  14.  
  15.     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  16.     {
  17.         throw new NotImplementedException();
  18.     }
  19. }
  20. public class ToDateConverter : IValueConverter
  21. {
  22.     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  23.     {
  24.         if (value == null)
  25.             return null;
  26.         DateTime? date = (DateTime)value;
  27.         if (date.HasValue)
  28.         {
  29.             if (date.Value.Date == DateTime.Now.Date)
  30.             {
  31.                 return "Today";
  32.             }
  33.             else if (date.Value.Date.Date == DateTime.Now.Date.AddDays(1))
  34.             {
  35.                 return "Tomorrow";
  36.             }
  37.             return date.Value.Date.ToShortDateString();
  38.         }
  39.         return null;
  40.     }
  41.  
  42.     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  43.     {
  44.         throw new NotImplementedException();
  45.     }
  46. }
  47. public class FromDateConverter : IValueConverter
  48. {
  49.     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  50.     {
  51.         if (value == null)
  52.             return null;
  53.         DateTime? date = (DateTime)value;
  54.         if (date.HasValue)
  55.         {
  56.             if (date.Value.Date == DateTime.Now.Date)
  57.             {
  58.                 return "Today";
  59.             }
  60.             else if (date.Value.Date.Date == DateTime.Now.Date.AddDays(-1))
  61.             {
  62.                 return "Yesterday";
  63.             }
  64.             return date.Value.Date.ToShortDateString();
  65.         }
  66.         return null;
  67.     }
  68.  
  69.     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  70.     {
  71.         throw new NotImplementedException();
  72.     }
  73. }
BulkObservableCollection:

Expand|Select|Wrap|Line Numbers
  1.   public class BulkObservableCollection<T> : IDisposable, INotifyCollectionChanged, INotifyPropertyChanged, IEnumerable<T>
  2. {
  3.     ConcurrentQueue<NotifyCollectionChangedEventArgs> _losts = new ConcurrentQueue<NotifyCollectionChangedEventArgs>();
  4.     Guid? _cancelToken = null;
  5.     private HashSet<Guid> _cancelTokensDict = null;
  6.     bool _isInAddRange = false;
  7.     bool _isLoading = true;
  8.     public bool IsLoading
  9.     {
  10.         get
  11.         {
  12.             lock (_locker)
  13.             {
  14.                 return _isLoading;
  15.             }
  16.         }
  17.     }
  18.     const string COUNT = "Count";
  19.     const string ITEMS = "Item[]";
  20.     public event NotifyCollectionChangedEventHandler CollectionChanged;
  21.     public event PropertyChangedEventHandler PropertyChanged;
  22.     List<T> _items = new List<T>();
  23.     IUpdateTotalItems _updateTotalItems = null;
  24.     public int Count => _items.Count;
  25.  
  26.     public BulkObservableCollection()
  27.     {
  28.     }
  29.  
  30.     public BulkObservableCollection(Guid cancelToken, ref HashSet<Guid> cancelTokensDict, IUpdateTotalItems updateTotalItems = null)
  31.     {
  32.         _cancelToken = cancelToken;
  33.         _cancelTokensDict = cancelTokensDict;
  34.         _updateTotalItems = updateTotalItems;
  35.     }
  36.  
  37.     readonly object _locker = new object();
  38.     public void LoadingFinished()
  39.     {
  40.         lock (_locker)
  41.         {
  42.             _isLoading = false;
  43.             BeginUpdate();
  44.         }
  45.     }
  46.  
  47.     public void Refresh()
  48.     {
  49.         EndUpdate();
  50.         UpdateTotalItems(_items.Count);
  51.         BeginUpdate();
  52.     }
  53.  
  54.     #region INotifyPropertyChanged
  55.  
  56.     private void OnPropertyChanged(string propertyName)
  57.     {
  58.         if (_isDispose)
  59.             return;
  60.         if (!_isInAddRange)
  61.         {
  62.             try
  63.             {
  64.                 var ev = this.PropertyChanged;
  65.                 if (ev != null)
  66.                 {
  67.                     ev(this, new PropertyChangedEventArgs(propertyName));
  68.                 }
  69.             }
  70.             catch (Exception ex)
  71.             {
  72.                 Trace.WriteLine($"OnPropertyChanged:: Error on FirePropertyChanged propertyName = {propertyName}, Error: {ex.Message}");
  73.             }
  74.         }
  75.     }
  76.  
  77.     #endregion INotifyPropertyChanged
  78.  
  79.     #region INotifyCollectionChanged
  80.  
  81.     private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
  82.     {
  83.         if (_isDispose)
  84.             return;
  85.         OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
  86.     }
  87.  
  88.     private void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
  89.     {
  90.         if (_isDispose)
  91.             return;
  92.         if (!_isInAddRange)
  93.         {
  94.             try
  95.             {
  96.                 var ev = this.CollectionChanged;
  97.                 if (ev != null)
  98.                 {
  99.                     ev(this, e);
  100.                 }
  101.             }
  102.             catch (Exception ex)
  103.             {
  104.                 Trace.WriteLine($"OnPropertyChanged:: Error on CollectionChanged Error: {ex.Message}");
  105.             }
  106.         }
  107.     }
  108.  
  109.     #endregion INotifyCollectionChanged
  110.  
  111.     #region Add 
  112.  
  113.     public void Add(T item)
  114.     {
  115.         if (_isDispose)
  116.             return;
  117.         if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  118.             return;
  119.        // int index = _items.Count;
  120.         InsertItem(0, item);
  121.     }
  122.  
  123.     public void Insert(int index, T item)
  124.     {
  125.         if (_isDispose)
  126.             return;
  127.         if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  128.             return;
  129.         InsertItem(index, item);
  130.     }
  131.  
  132.     private void InsertItem(int index, T item)
  133.     {
  134.         if (_isDispose)
  135.             return;
  136.         if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  137.             return;
  138.         _items.Insert(index, item);
  139.         OnPropertyChanged(COUNT);
  140.         OnPropertyChanged(ITEMS);
  141.         OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
  142.     }
  143.  
  144.     public void AddRange(T[] array)
  145.     {
  146.         if (_isDispose)
  147.             return;
  148.         if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  149.             return;
  150.         if (array == null)
  151.             throw new ArgumentNullException("array");           
  152.         BeginUpdate();
  153.         for (int i = 0; i < array.Length; i++)
  154.         {
  155.             if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  156.                 break;
  157.             var item = array[i];
  158.             if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  159.                 break;
  160.             Add(item);
  161.         }
  162.         EndUpdate();
  163.     }
  164.  
  165.     public void AddRange(List<T> list)
  166.     {
  167.         if (_isDispose)
  168.             return;
  169.         if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  170.             return;
  171.         if (list == null)
  172.             throw new ArgumentNullException("list");
  173.  
  174.         BeginUpdate();
  175.         for (int i = 0; i < list.Count; i++)
  176.         {
  177.             if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  178.                 break;
  179.             var item = list[i];
  180.             if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  181.                 break;
  182.             Add(item);
  183.         }
  184.         EndUpdate();
  185.     }
  186.  
  187.     #endregion Add 
  188.  
  189.     #region Remove
  190.  
  191.     public bool Remove(T item)
  192.     {
  193.         if (_isDispose)
  194.             return false;
  195.         if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  196.             return false;
  197.         int index = _items.IndexOf(item);
  198.         if (index < 0) return false;
  199.         RemoveItem(item, index);
  200.         return true;
  201.     }
  202.  
  203.     private void RemoveItem(T removedItem, int index)
  204.     {
  205.         _items.RemoveAt(index);
  206.         OnPropertyChanged(COUNT);
  207.         OnPropertyChanged(ITEMS);
  208.         OnCollectionChanged(NotifyCollectionChangedAction.Remove, removedItem, index);
  209.     }
  210.  
  211.     #endregion Remove
  212.  
  213.     #region Clear
  214.  
  215.     public void Clear()
  216.     {
  217.         if (_isDispose)
  218.             return;
  219.         if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  220.             return;
  221.         _items.Clear();
  222.         OnPropertyChanged(COUNT);
  223.         OnPropertyChanged(ITEMS);
  224.         OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
  225.     }
  226.  
  227.     #endregion Clear
  228.  
  229.     #region GetEnumerator
  230.  
  231.     public IEnumerator<T> GetEnumerator()
  232.     {
  233.         return _items.GetEnumerator();
  234.     }
  235.  
  236.     IEnumerator IEnumerable.GetEnumerator()
  237.     {
  238.         return ((IEnumerable)_items).GetEnumerator();
  239.     }
  240.  
  241.     #endregion GetEnumerator
  242.  
  243.     #region Dispose
  244.  
  245.     bool _isDispose = false;
  246.     public void Dispose()
  247.     {
  248.         if (!_isDispose)
  249.         {
  250.             _isDispose = true;
  251.             if (_cancelToken != null && _cancelTokensDict != null)
  252.             {
  253.                 _cancelTokensDict.Add(_cancelToken.Value);
  254.             }
  255.             if (_items != null)
  256.             {
  257.                 _items.Clear();
  258.             }
  259.             while (_losts.TryDequeue(out NotifyCollectionChangedEventArgs item))
  260.             { // do nothing
  261.             }
  262.         }
  263.     }
  264.  
  265.     #endregion Dispose
  266.  
  267.     public void BeginUpdate()
  268.     {
  269.         if (_isDispose)
  270.             return;
  271.         _isInAddRange = true;
  272.     }
  273.  
  274.     public void EndUpdate()
  275.     {
  276.         if (_isDispose)
  277.             return;
  278.         _isInAddRange = false;
  279.         OnPropertyChanged(COUNT);
  280.         OnPropertyChanged(ITEMS);
  281.         OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
  282.     }
  283.  
  284.     public void UpdateTotalItems(int count)
  285.     {
  286.         if (_updateTotalItems != null)
  287.         {
  288.             _updateTotalItems.UpdateTotalItems(count);
  289.         }
  290.     }
  291.  
  292.     public void Enqueue(NotifyCollectionChangedEventArgs e)
  293.     {
  294.         bool sendToHandle = false;
  295.         lock (_locker)
  296.         {
  297.             if (!_isLoading)
  298.             {
  299.                 sendToHandle = true;
  300.             }
  301.         }
  302.         if (sendToHandle)
  303.         {
  304.             Handle(e);
  305.         }
  306.         else
  307.         {
  308.             lock (_losts)
  309.             {
  310.                 _losts.Enqueue(e);
  311.             }
  312.         }
  313.     }
  314.  
  315.     public void PopulateFromLost()
  316.     {
  317.         if (_isDispose)
  318.             return;
  319.         if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  320.             return;
  321.  
  322.         lock (_losts)
  323.         {
  324.             while (_losts.TryDequeue(out NotifyCollectionChangedEventArgs e))
  325.             {
  326.                 if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  327.                     break;
  328.                 Handle(e);
  329.             }
  330.         }
  331.     }
  332.  
  333.     private void Handle(NotifyCollectionChangedEventArgs e)
  334.     {
  335.         if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  336.             return;
  337.         switch (e.Action)
  338.         {
  339.             case NotifyCollectionChangedAction.Add:
  340.                 {
  341.                     foreach (var item in e.NewItems)
  342.                     {
  343.                         try
  344.                         {
  345.                             if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  346.                                 break;
  347.  
  348.                             _items.Insert(e.NewStartingIndex, (T)item);
  349.                         }
  350.                         catch (Exception ex)
  351.                         {
  352.                             Trace.WriteLine($"Handle:Add, e.NewStartingIndex:{e.NewStartingIndex}, Error:{ex.Message}");
  353.                         }
  354.                     }
  355.                 }
  356.                 break;
  357.             case NotifyCollectionChangedAction.Remove:
  358.                 {
  359.                     foreach (var item in e.OldItems)
  360.                     {
  361.                         try
  362.                         {
  363.                             if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  364.                                 break;
  365.  
  366.                             _items.Remove((T)item);
  367.                         }
  368.                         catch (Exception ex)
  369.                         {
  370.                             Trace.WriteLine($"Handle:Remove, Error:{ex.Message}");
  371.                         }
  372.                     }
  373.                 }
  374.                 break;
  375.             case NotifyCollectionChangedAction.Move:
  376.                 {
  377.                     try
  378.                     {
  379.                         if (_cancelTokensDict != null && _cancelToken.HasValue && _cancelTokensDict.Contains(_cancelToken.Value))
  380.                             break;
  381.  
  382.                         var itemMoved = (T)e.OldItems[0];
  383.                         _items.Remove(itemMoved);
  384.                         _items.Insert(e.NewStartingIndex, itemMoved);
  385.                     }
  386.                     catch (Exception ex)
  387.                     {
  388.                         Trace.WriteLine($"Handle:Move, e.OldStartingIndex:{e.OldStartingIndex}, e.NewStartingIndex:{e.NewStartingIndex}, Error:{ex.Message}");
  389.                     }
  390.                 }
  391.                 break;
  392.         }
  393.     }
  394. }
3 Weeks Ago #1
0 5388

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

1 post views Thread by serge calderara | last post: by
17 posts views Thread by kalamos | last post: by
3 posts views Thread by pkumar | last post: by
3 posts views Thread by Asim Qazi | last post: by
2 posts views Thread by Jassim Rahma | last post: by
Sl1ver
1 post views Thread by Sl1ver | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.