Как оптимизировать итерацию узлов через параллельный LOP? - PullRequest
0 голосов
/ 15 февраля 2019

У меня есть список узлов в древовидном списке.

Иногда я включаю сортировку по столбцам и, чтобы сохранить ту же структуру / положение узлов, я копирую структуру как есть, помещаю ее в список, и когда деактивация сортировки выполняется, явернуть позиции ноди.Это делается так:

        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)
        {


        }

Я получаю какой-то странный результат.Большую часть времени узлы в пользовательском интерфейсе исчезают, и время от времени я получаю исключение нулевой ссылки, которое еще больше смущает меня.

Что я здесь упускаю?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Оказывается, что у Devexpress есть методы BeginUpdate() и EndUpdate().

Я использовал их, и они значительно оптимизировали рендеринг моего дерева.модифицированное решение:

Вместо параллели для меня теперь есть:

        xtlItemList.BeginUpdate();
        for (int i = 0; i < nodes.Count; i++)
        {
            xtlItemList.SetNodeIndex(nodes[i], i);
        }
        xtlItemList.EndUpdate();

Документация:

Метод начала

Метод завершения

0 голосов
/ 16 февраля 2019

Я предполагаю, что вы используете DevExpress XtraTreeList в приложении Windows Forms.

Как и в случае с Parallel.for, он запускает выполнение в нескольких потоках, в отличие от основного потока пользовательского интерфейса.Небезопасно манипулировать элементами управления пользовательского интерфейса из потока, не являющегося пользовательским интерфейсом, это приводит к непредсказуемым результатам:

https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls

Потокобезопасные вызовы элементов управления WPF

Кроме того, я чувствую, что параллельные циклы также не сделают это намного быстрее, поскольку процесс не связан с фоновой работой.

Я не эксперт по элементам управления пользовательского интерфейса DevExpress, но для вашегореальная проблема, вы можете создать дополнительный скрытый столбец в вашем TreeList, заполнить его исходными значениями индекса (такими как 1,2,3 ..) и отсортировать его узлы первоначально по этому столбцу.Затем позже вы можете восстановить свой XtraTreeList, снова сортируя по этому столбцу, как предложено здесь:

https://www.devexpress.com/Support/Center/Question/Details/A2372/how-to-clear-column-sorting-and-restore-the-nodes-to-their-original-order

Я думаю, это будет работать намного быстрее.

Надеюсь, это поможет решитьтвоя проблема ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...