Я создаю приложение, которое имеет некоторые простые функции сниффера и которое показывает сброшенные пользователем пакеты. Пакеты считываются из файла дампа, который обновляется в режиме реального времени с текущим трафиком, а затем захваченные пакеты добавляются в Datagrid (каждый пакет — новая строка). Я использую привязку данных для получения пакетов из считывателя дампа, который реализует интерфейс ICollectionChanged, поэтому Datagrid информируется о каждом новом пакете. Datagrid использует виртуализацию и отложенную прокрутку. Почти все работает нормально, за исключением большого потребления процессора. Эта загрузка ЦП вызвана тем, что я читаю все новые пакеты (тысячи в секунду), форматирую их для отображения и для каждого пакета возникает событие CollectionChanged, которое обновляет Datagrid. Требование к программному обеспечению состоит в том, что пользователю не обязательно видеть все новые пакеты в режиме реального времени - их появляются десятки тысяч в секунду, так что никто их все не заметит. Пользователь может просматривать только некоторые пакеты, и когда он хочет, он может прокручивать полосу вниз / вверх до соответствующей позиции, чтобы увидеть нужные ему пакеты, и только в этом случае пакеты должны быть прочитаны из файла.
Проблема в том, что я хочу, чтобы Datagrid обновлялся каждую секунду, чтобы показать, что новые пакеты прибыли, предпочтительно путем масштабирования полосы прокрутки до фактического количества пакетов, но без необходимости их непрерывного чтения, форматирования и вызова CollectionChanged, потому что это требует процессорного времени, и, кроме того, пользователь не увидит новые пакеты, если он не прокручивает полосу. Мне сообщают количество прибывающих пакетов, поэтому я знаю количество всех пакетов.
Я попытался добавить поддельные пакеты (тем самым избегая чтения и форматирования каждого нового пакета) только для того, чтобы заставить Datagrid масштабироваться до фактического количества пакетов. Это почти сработало, потому что загрузка ЦП падает, а пакеты читаются только при прокрутке полосы. Но через мгновение, когда в Datagrid добавлялись новые пакеты, строки в текущем представлении начинали произвольно дублироваться, т.е. в первый момент пакет в представлении отображался 1-й, 2-й, 3-й, 4-й, 5-й, 6-й и так далее, но через некоторое время они отображались 1-м, 2-м, 3-м и снова 1-м, 2-м, 3-м.
Я также попытался обновить привязку - это сработало, но потребляло больше ресурсов, чем при первом подходе, поэтому я отказался от него. Я также попытался обновить список коллекции Datagrid - тот же эффект, что и при обновлении привязки.
Следующее, что когда я хотел добавить список пакетов за один вызов CollectionChanged
NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, list));
Я получил сообщение об ошибке, что действия диапазона не поддерживаются, вызванные PresentationFramework.dll!System.Windows.Data.ListCollectionView.ValidateCollectionChangedEventArgs(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
Поэтому мне пришлось вызывать CollectionChanged для каждого пакета в списке пакетов, что также увеличивало нагрузку на ЦП.
Подводя итог, я хотел бы сообщить Datagrid, что есть новые пакеты/строки, поэтому полоса прокрутки Datagrid будет масштабироваться до общего количества пакетов, но пакеты будут считываться из файла только тогда, когда пользователь прокручивает полосу .
Я был бы очень благодарен за каждое предложение, как решить мою проблему.
Я только что понял, что есть одна важная вещь, которую нужно упомянуть, и извините, я забыл сказать об этом в начале. Моя ObservableCollection поддерживает какую-то виртуализацию данных, когда в памяти я держу лишь несколько необходимых пакетов. Когда приходят новые пакеты, я просто сообщаю своей коллекции о количестве новых пакетов, и мне не нужно вызывать метод Add для сбора, потому что я на самом деле не добавляю в нее никаких пакетов, поэтому никакие пакеты фактически не считываются< /сильный>. Коллекция содержит информацию об общем количестве пакетов в данный момент, и только небольшое их количество действительно хранится в памяти, чтобы сетка могла их отображать. Пакеты считываются на лету только при необходимости, а когда они не отображаются, они освобождаются. Но чтобы сообщить grid о новых пакетах, я должен (я не знаю, как это сделать по-другому, лучше) вызвать CollectionChanged и в аргументе этого вызова мне нужно подавать каждый новый пакет. И этот вызов CollectionChanged заставляет пакеты действительно читаться, что потребляет процессор. Я хочу перемасштабировать сетку, чтобы размер полосы прокрутки информировал о поступлении новых пакетов, но без необходимости чтения пакетов и вызова CollectionChanged по одному для каждого нового пакета (что может происходить тысячу раз в секунду). Я хочу, чтобы пакеты читались только при изменении положения полосы прокрутки, поэтому дорогостоящие операции обработки каждого пакета будут выполняться только для нескольких видимых в данный момент пакетов, а не для каждого пакета.