ObservableCollection触发了太多的CollectionChanged

时间:2015-04-03 12:12:19

标签: c# wpf

我在下面使用此代码执行通过以太网连接收集的 ObservableCollection 消息的异步更新

ObservableCollection

private readonly ObservableCollection<MsgDisplayViewModel> _rxGridMessages;
public ObservableCollection<MsgDisplayViewModel> RxGridMessages
{
    get { return _rxGridMessages; }
}

Action

_rxMsgUpdater = new Action<RxMessage>((RxMessage msg) =>
    {
        if (_rxGridMessages.Count < 2000)
        {
            _rxGridMessages.Add(new MsgDisplayViewModel(msg, DataCollection.DataBase));
        }
        else
        {
            var dispmsg = new MsgDisplayViewModel(msg, DataCollection.DataBase);
            _rxGridMessages[index++ % _rxGridMessages.Count] = dispmsg;
        }
    }
);
背景线程从 BeginInvoke

调用

RxEventHandler

    private void RxEventHandler(RxMessage msg)
    {
        UiDispatcher.BeginInvoke(_rxMsgUpdater, DispatcherPriority.Normal, msg);
    }

XAML

<DataGrid Name="TraceGrid" 
     ItemsSource="{Binding MyVm.RxGridMessages, Mode=OneWay, IsAsync=True}"
     SelectionMode="Single"  AutoGenerateColumns="False" VirtualizingPanel.IsVirtualizing="True" FontSize="10" 
     HorizontalAlignment="Stretch"  IsReadOnly="True" RowDetailsVisibilityMode="Visible" BorderBrush="{DynamicResource AccentColorBrush}" BorderThickness="1"   EnableColumnVirtualization="True"
          EnableRowVirtualization="True" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.IsDeferredScrollingEnabled="True"                        
          >
    <DataGrid.Columns>

...

只要后台主题每秒调用 RxEventHandler 20次,UI就会很好。 一旦我将实际流量输入, RxEventHandler 就会被称为每秒1000次。

所以我通过扩展 ObservableCollection 尝试了一些事情,我开始在 {{ OnCollectionChanged 的基础上收集更改的项目1}} 并每隔500毫秒触发 ObservableCollection 事件。 它显然抛出 CollectionChanged 而我不得不使用以下内容,

RangeNotSupportedException

问题是集合是重建的,并且在显示之前有一些延迟。如果收集项目数量很少,则非常快。但是当它达到1000左右时则需要几秒钟。

我正在向数据网格提供这个,如上所示,我也启用了 try { base.OnCollectionChanged(new System.Collections.Specialized.NotifyCollectionChangedEventArgs(System.Collections.Specialized.NotifyCollectionChangedAction.Add, addedItems, itemaddedindex)); } catch (System.NotSupportedException) { base.OnCollectionChanged(new System.Collections.Specialized.NotifyCollectionChangedEventArgs(System.Collections.Specialized.NotifyCollectionChangedAction.Reset)); } 。现在我已经做了很多谷歌搜索,我没有找到一个解决这个问题的人。 任何人都可以就此提出建议吗?

我做了一些分析,CPU占用了 Virtualization ,它似乎与众多 PresentationFramework.ni.dll 事件有关。 现在我有一些响应,但代价是限制收集计数。这不是我想要做的。

2 个答案:

答案 0 :(得分:2)

由于此问题的性质,您应该使用某种类型的处理队列,然后创建一个处理单独处理的处理程序。此外,由于您正在使用大量数据,您应该使用计时器每x秒/分钟查询新更新并以这种方式刷新datagrid,或者您应该使用某种类型的虚拟化面板来处理纯粹的数量传递给它的数据(ListView / GridView)

答案 1 :(得分:1)

Visual Studio 2015中的新功能

BulkObservableCollection

https://msdn.microsoft.com/en-us/library/dd867973.aspx