Оптимизировать вложенный цикл for

Я использую библиотеку GMAP.Net для картографического приложения Windows. У меня около 17000 полигонов в моей базе данных Sql Server. В событии загрузки формы я выбираю все полигоны из базы данных и заполняю таблицу данных, а затем рисую полигоны один за другим из таблицы данных. У меня также есть древовидное представление, в которое я добавляю все 17000 имен полигонов. Теперь, когда я устанавливаю флажок «Выбрать все» в дереве, я вызываю функцию в событии Treeview node_AfterCheck следующим образом:

Private Sub node_AfterCheck(sender As Object, e As TreeViewEventArgs)     Handles TreeView1.AfterCheck

   If e.Action <> TreeViewAction.Unknown Then
      Task.Factory.StartNew(Sub()
                                  GetPolygons(e.Node)
                              End Sub, TaskCreationOptions.LongRunning)
   End If
End Sub



Private Sub GetPolygons(node As TreeNode)
            Dim objectId As String
            Dim _polygon As GMapPolygon
            For Each node1 As TreeNode In node.Nodes
                objectId = node1.Name

                For Each _polygon In polyOverlay.Polygons.AsParallel
                    itemTag = _polygon.Tag.ToString.Split("|")
                    If itemTag (0) = node1.Name Then
                        _polygon.IsVisible = node.Checked
                        Exit For
                    End If
                Next
            Next
End sub

для полного выполнения этого кода требуется около 40 секунд. Есть ли способ оптимизировать этот код для выполнения в более короткие сроки?


person Behnam Faghih    schedule 14.01.2016    source источник
comment
Также есть некоторые проблемы с порядком End If и Exit For.   -  person rdoubleui    schedule 14.01.2016


Ответы (2)


Единственное, что я вижу, является дорогостоящим с точки зрения кода, это вызов Split для тегов полигона. Но это подлежит измерению.

Чтобы обойти Split, вы можете, например. попробуй использовать:

If _polygon.Tag.StartsWith(node1.Name) Then

Рассмотрите этот вопрос, чтобы узнать, является ли IsPrefix даже в вашем случае быстрее.

Однако я предполагаю, что основная проблема заключается в постоянном обновлении/перерисовке карты («автоматическое обновление») при настройке видимости каждого полигона. Одна вещь, которую я нашел в источниках, это установить Invalidation на удержание:

// docs: stops immediate markers/route/polygon invalidations; call Refresh to perform single refresh and reset incalidation state
gmap2.HoldInvalidation = true;

// do your update loop within here

// docs: call this to stop HoldInvalidation and perform single forced instant refresh
gmap2.Refresh();

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

person rdoubleui    schedule 14.01.2016

спасибо за ваш быстрый ответ, я изменил свой код следующим образом:

Private Sub GetPolygons(node As TreeNode)

        myMap.HoldInvalidation = True

        Dim objectId As String
        Dim _polygon As GMapPolygon
        For Each node1 As TreeNode In node.Nodes
            objectId = node1.Name

            For Each _polygon In polyOverlay.Polygons.AsParallel
                itemTag = _polygon.Tag.ToString.Split("|")
                If itemTag (0) = node1.Name Then
                    _polygon.IsVisible = node.Checked
                    Exit For
                End If
            Next
        Next

        myMap.Refresh()

Конец сабвуфера

но выполнение кода занимает больше времени, чем раньше.

person Behnam Faghih    schedule 14.01.2016
comment
путем замены _polygon.Tag.ToString.Split(|) на _polygon.Tag.StartsWith(node1.Name) теперь код занимает около 20 секунд, а не 40 секунд. - person Behnam Faghih; 14.01.2016
comment
Ладно, стоило попробовать. 17000 полигонов - это совсем немного, рад видеть, что удаление операции Split помогло, все же, возможно, даже лучше без какой-либо операции над каждой строкой, как думаете, это возможно? Сколько времени на самом деле занимает эта операция? Выясните это, вообще исключив настройку видимости, чтобы попытаться сузить область, где находится узкое место. Посмотрим, что мы получим оттуда, я хочу знать. - person rdoubleui; 14.01.2016
comment
Без операции над каждой строкой это занимает около 2 секунд! - person Behnam Faghih; 16.01.2016
comment
Хорошие новости: пришло время реорганизовать эту string операцию из цикла. Теперь, когда вы дошли до реальных долей секунд, которые могут иметь значение, мне было бы интересно, имеет ли значение HoldInvalidation. - person rdoubleui; 16.01.2016
comment
Нет HoldInvalidation не имеет значения. но хорошие новости! Я поместил polygonId в polygon.name вместо polygon.tag, теперь я просто проверяю: полный. Теперь, если я могу удалить это, если я думаю, что это будет более оптимизировано - person Behnam Faghih; 17.01.2016