У меня есть список узлов в древовидном списке.
Иногда я отключаю сортировку по столбцам и, чтобы сохранить ту же структуру/положение узлов, копирую структуру как есть, помещаю ее в список, а когда деактивация сортировки завершена, возвращаю позиции узлов. Это делается так:
List<TreeListNode> nodes = new List<TreeListNode>();
nodes.AddRange(xtlItemList.Nodes);
// deactivete sorting
foreach (var c in xtlItemList.Columns) {
c.SortOrder = SortOrder.None;
}
// put back node positions
for (int i = 0; i < nodes.Count; i++)
{
xtlItemList.SetNodeIndex(nodes[i], i);
}
Проблема:
Разве что выполнение второго цикла занимает много времени. Для 1043 узлов это занимает до 50 секунд.
Я думал, что смогу оптимизировать его с помощью параллельного цикла for:
int counter = nodes.Count -1;
try
{
Parallel.For
(0
, counter
, new ParallelOptions { MaxDegreeOfParallelism = 5 }
, (i) =>
{
try
{
xtlItemList.SetNodeIndex(nodes[i], i);
}
catch (Exception exception)
{
//throw;
}
}
);
}
catch (Exception exx)
{
}
Я получаю какой-то странный результат. в большинстве случаев узлы в пользовательском интерфейсе исчезают, и время от времени я получаю исключение с нулевой ссылкой, что еще больше меня смущает.
Что мне здесь не хватает?





Я предполагаю, что вы используете DevExpress XtraTreeList в приложении Windows Forms.
Что касается parallel.for, то он порождает выполнение в нескольких потоках, отличных от основного потока пользовательского интерфейса. Небезопасно манипулировать элементами управления пользовательского интерфейса из потока, отличного от пользовательского интерфейса, это приводит к непредсказуемым результатам:
Поточно-ориентированные вызовы элементов управления WPF
Кроме того, я чувствую, что параллельные циклы также не сделают это намного быстрее, поскольку процесс не связан с фоновой работой.
Я не эксперт по элементам управления DevExpress UI, но для вашей реальной проблемы вы можете создать дополнительный скрытый столбец в своем TreeList, заполнить его исходными значениями индекса (например, 1,2,3..) и отсортировать его узлы изначально по этому столбцу. Затем позже вы можете снова восстановить свой XtraTreeList, отсортировав его по этому столбцу, как предлагается здесь:
Я думаю, это будет работать намного быстрее.
Надеюсь, это поможет решить вашу проблему.
Оказывается, у Devexpress есть методы BeginUpdate() и EndUpdate().
Я использовал их, и они значительно оптимизировали рендеринг моего дерева. модифицированное решение:
Вместо параллели у меня теперь есть:
xtlItemList.BeginUpdate();
for (int i = 0; i < nodes.Count; i++)
{
xtlItemList.SetNodeIndex(nodes[i], i);
}
xtlItemList.EndUpdate();
Документация:
Я не хотел создавать столбец для хранения временных данных, поэтому я создал список, который я показываю в своем коде, и это то же самое, что вы описываете. Проблема в том, что когда я восстанавливаю позиции узлов (1, 2, 3), это занимает время, поэтому параллель для