Improve UI performance on heavy work loop

时间:2015-11-12 11:47:09

标签: c# .net vb.net performance loops

I have a "time line" in my application, consisting of many labels (dynamic) that get placed according to their relative position in the time scale.

I have another section below this, which is the "legends" section for the time line. When hovering over a particular legend, I step through the time line, and set all the non relevant labels to visible = false, and the relevant labels to visible. This allows the user to hover over a certain legend label, and see it represented alone on the time line.

Extra Info When a user exits the legend(label) hover, I restore all the lines (labels) on the timeline to visible. /Extra info

This all works really well, but some of my time scales, have 800+ labels on them (thin lines).

The interface updates in about 3-5 seconds in this case, which is acceptable, but the CPU REALLY battles to keep up.

When testing, my music player stutters big time whenever I run this code to interact with the time line. As soon as the loop is finished, the cpu catches up again.

As I really don't want to use a doEvents() (not that it really helps.. I tried), what other suggestions can you offer to give the cpu some breathing time.

What I have done so far:

  1. Set the containing panel to invisible before the loop begins, and visible when it completes.
  2. Suspend and Resume layout does not seem to make any difference to performance, I had better results with the visibility trick in point 1.
  3. I am already re-using labels, and don't add/remove them when I need to show them.
  4. Should I implement threading.thread.sleep, just for a few milliseconds, after each loop iteration? (Is this acceptable practice)
  5. My form is set to double buffered.
  6. The labels may be a bit "heavy", as they have a plethora of extra properties and features/events that I don't use. Is there a better alternative?

My code:

 Private Sub label_hovered(appname As String) Handles myAwesomeViewLegend.labelHover

        Try

            blockPanel.Visible = False

            For Each l As Label In blockPanel.Controls
                If l.Text = appname Then
                    l.Visible = True

                Else
                    l.Visible = False
                End If

            Next

            blockPanel.Visible = True

        Catch ex As Exception
            Dim method_name As String = System.Reflection.MethodBase.GetCurrentMethod().Name
            Dim method_class As String = System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.FullName
            MsgBox(ex.tostring & vbcrlf & vbcrlf & method_name & vbcrlf & vbcrlf & method_class)
        End Try
    End Sub

1 个答案:

答案 0 :(得分:1)

I would construct only the visible labels. I think it is a bad practice creating 800 labels and toggle the Visibility property.

Create a sorted list with times and check if a time should be visible by calculating the start and endtime (window). Create labels for the (should be visible) times.