Поток пользовательского интерфейса останавливается при загрузке и обновлении объекта RadGridView - PullRequest
2 голосов
/ 29 июля 2011

Всем днем,

В настоящее время я профилирую довольно большое приложение CF WPF, пытаясь устранить некоторые проблемы с производительностью.Один включает 5-8 секундную остановку, которая происходит при переключении на определенный (довольно большой) UserControl.Я сузил это до RadGridView, содержащегося в этом UserControl, который долго загружался и обновлялся, останавливая поток пользовательского интерфейса и делая все приложение не отвечающим.Очевидно, что мы хотели бы устранить эту остановку, если это возможно.

Я пытался убрать любые пользовательские стили и DataTriggers в сетке, но в то время как это действовало, чтобы уменьшить нагрузку на поток пользовательского интерфейса в целом, остановка все ещеостался, казалось бы, не уменьшился.Через ANTS Profiler кажется, что в основном виноваты измерения и расположение сетки, а также некоторая загрузка шаблонов XAML.При отсутствии строк сетки, UserControls загружается значительно быстрее, и кажется, что добавления небольшого количества строк достаточно для того, чтобы вызвать остановку.В сетке включена виртуализация для строк и столбцов, но это, похоже, не помогает.График вызовов чрезвычайно глубок при рассмотрении, и кажется, что это вызовы, которые поднимают уведомления об обновлениях, макет обновления, загружают XAML и, прежде всего, измеряют дочерние FrameworkElements, которые виноваты.

Для пары потенциальных решенийЯ думаю о сохранении UserControl в памяти, но скрытом, чтобы уменьшить затраты на его переключение или заполнение сетки, возможно, постепенно, после загрузки UserControl.С первым может быть много работы, так как элемент управления подписывается на несколько вещей, которые необходимо подключить, отключить и повторно подключить в зависимости от ситуации.Последнее может также потребовать немалой работы, но может быть лучшим решением, потому что тогда, по крайней мере, мы могли бы попытаться самим уменьшить задержку или, по крайней мере, предупредить пользователя, когда это произошло.

Еслипроблема сохраняется, мы, вероятно, попросим Telerik взглянуть на нее, но я решил сначала спросить здесь, если кто-то сталкивался с такой проблемой раньше (не обязательно даже с RadGridView) и нашел решение некоторого описания.

Приветствия.

1 Ответ

0 голосов
/ 25 марта 2017

Проблема в том, что вам нужна коллекция, которая правильно реализует ICollectionChanged.

Попробуйте это после добавления всех записей в вашу исходную коллекцию (ту, которая НЕ должна вызывать какие-либо события CollectionChanged после каждого добавления), она работает:

public void AddRange(List<TValue> values, int startingIndex)
{
    // add all the items to your internal list, but avoid raising events.

    // now raise CollectionChanged with an IList type.
    CollectionChanged?.Invoke(collection, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, addedValues, startingIndex));
}

Обратите внимание, мы проходим IList<TValue>, НЕ TValue. Когда он видит список, он добавляет их ВСЕ перед обработкой. Начальным значением обычно является .Count в списке до того, как вы начали добавлять элементы.

Шаги:

  1. Подкласс типа коллекции, который еще не реализует INotifyCollectionChanged. Существует множество примеров с открытым исходным кодом.
  2. Добавьте метод выше и используйте его после того, как добавили свои элементы.
  3. Мой RadGridView связывается с QueryableCollectionView, который использует этот список в качестве SourceCollection. Я не знаю, можете ли вы связываться с этим списком напрямую.

Одно странное поведение с RadGridView состоит в том, что если вы добавите, скажем, миллион записей таким образом, это будет быстро, но все строки новые будут пустыми, и вы сможете наблюдать, как RadGridView медленно заполняет их данные от самого верхнего нового элемента вниз. Мое решение состоит в том, чтобы связать QueryableCollection и установить его PageSize достаточно маленьким, чтобы пользователи этого не видели.

...