0
votes

How can I update Chart by thread timer. I not use invoke like this code.

  Chart1.BeginInvoke(New MethodInvoker(Sub()
        Showdatatimer()
        End Sub))

Because it freeze UI not difference from no thread.

So I try to use System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False Code like this

 Private Sub Barfrmvb_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False

        Dim TDS1 As TimerCallback = AddressOf Showdatatimer
        Timer_LoadData = New Threading.Timer(TDS1, Nothing, 0, 3000)
  End Sub
Sub Showdatatimer()
        Timer_LoadData.Change(Timeout.Infinite, Timeout.Infinite)
        Try
          Dim s As SeriesCollection
            s = Chart1.Series

            For i = 0 To 100
                Dim s1 As New Series
                s1.ChartType = SeriesChartType.StackedBar
                s1.Points.AddXY(1, Now.Second + i)
                s.Add(s1)
            Next
        Catch ex As Exception
        Finally
            Timer_LoadData.Change(1000, 1000)
        End Try

When Series less than 10 not a problem but serie more than I got error

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.DataVisualization.dll

Additional information: Collection was modified; enumeration operation may not execute.

I think 
1.Thread1 Showdatatimer Complete
2.UI Chart render from Thread1  not complete
3.Thread2 Showdatatimer Complete
4.UI Chart render Collection was modified

I try to use with dotnetcharting 500 series it work but dotnetcharting no StackedBar

Reason of 100 series.I will implement to show timeline status of machine yellow,green,red,blue. Anyone have other way suggest me please.

enter image description here

this code:

Public Sub Showdata(UserDT As DataTable, fromtime As DateTime, totime As DateTime)
 Chart1.Series.Clear()
            Chart1.ChartAreas("ChartArea1").Position.X = 0
            Chart1.ChartAreas("ChartArea1").Position.Width = 100
            Chart1.ChartAreas("ChartArea1").AxisY.Minimum = fromtime.ToOADate
            Chart1.ChartAreas("ChartArea1").AxisY.Maximum = totime.ToOADate
                Dim nexttime As DateTime
                For i = 0 To UserDT.Rows.Count - 2
                    Dim dr As DataRow
                    dr = UserDT.Rows(i)
                    Dim sname As String = i
                    nexttime = UserDT.Rows(i + 1)("rectime")
                    Dim befUsetime As TimeSpan
                    If i = 0 Then
                        dr("usetime") = nexttime.ToString("yyyy-MM-dd HH:mm:ss")
                    Else
                        dr("usetime") = nexttime.Subtract(CDate(dr("rectime")))

                    End If

                    If Chart1.Series.IndexOf(sname) = -1 Then
                        Chart1.Series.Add(New Series(sname))
                    End If

                    Chart1.Series(sname).YValueType = ChartValueType.DateTime


                    If dr("s").ToString = "R" Then
                        Chart1.Series(sname).Color = Color.Red
                    ElseIf dr("s").ToString = "Y" Then
                        Chart1.Series(sname).Color = Color.Yellow
                    ElseIf dr("s").ToString = "G" Then
                        Chart1.Series(sname).Color = Color.LimeGreen
                    ElseIf dr("s").ToString = "idle" Then
                        Chart1.Series(sname).Color = Color.White
                    ElseIf dr("s").ToString = "Beaktime_Start" Then
                        Chart1.Series(sname).Color = Color.Blue
                    Else
                        Chart1.Series(sname).Color = Color.Gray
                    End If

                    Chart1.Series(sname).ChartType = SeriesChartType.StackedBar
                    Dim x As String
                    Dim y As Double
                    x = dr("username").ToString
                    If i = 0 Then
                        y = CDate(dr("usetime")).ToOADate
                        Chart1.Series(sname).Points.AddXY(x, y)
                    Else
                        Dim t As TimeSpan = TimeSpan.Parse(dr("usetime"))
                        Chart1.Series(sname).Points.AddXY(x, New DateTime(t.Ticks).ToOADate)
                    End If

                Next
    End sub

I try another way to reduce series if can add in one series but different color.I try this code but same color.

 Chart1.SuspendLayout()
                                                 Chart1.Series.Clear()


                                                 Dim s As SeriesCollection
                                                 s = Chart1.Series
        Dim s1 As New Series
        For i = 0 To 500

            s1.ChartType = SeriesChartType.StackedBar
            Dim p As New DataPoint

            p.XValue = 1
            p.YValues = {Now.Second + i}
            If i Mod 2 = 0 Then
                p.Color = Color.Aqua
            ElseIf i Mod 3 = 0 Then
                p.Color = Color.White
            Else
                p.Color = Color.Red
            End If

            s1.Points.Add(p)

        Next
        s.Add(s1)
        Chart1.ResumeLayout()

enter image description here

Solve Stack Bar not change color add most value to first point and reduce value like this code. I will try to new algorithm add last value to first value.

 For i = 0 To 500

            s1.ChartType = SeriesChartType.StackedBar
            Dim p As New DataPoint

            p.XValue = 1
            p.YValues = {500 - i}
            If i Mod 2 = 0 Then
                p.Color = Color.Aqua
            ElseIf i Mod 3 = 0 Then
                p.Color = Color.White
            Else
                p.Color = Color.Red
            End If

            s1.Points.Add(p)

        Next

Result: enter image description here

1
You should never set CheckForIllegalCrossThreadCalls to False, so you should just go ahead and remove that again. The only way to access the UI from a background thread is to invoke. If doing so causes your UI to freeze then your Showdatatimer() method is doing some long-running work it shouldn't do. You never showed us in what context you are performing the invoke.Visual Vincent
Is there a reason as to why you're not using a System.Windows.Forms.Timer? (which runs on the UI thread)Visual Vincent
Is there a reason you are adding 100 data series with one point each? If you use one data series with 100 points you'll probably get better performance.John Wu
Also, use SuspendLayout for long updates and it will go much faster.John Wu
Chart1.SuspendLayout() Do somthing Chart1.ResumeLayout() right?Dome

1 Answers

0
votes

I try to implement one series code it work with seperate thread and UI thread no freeze. That reduce and very simple code than old.

 Public Sub Showdata(UserDT As DataTable, fromtime As DateTime, totime As DateTime)



        Try
            Chart1.Series.Clear()
            Chart1.ChartAreas("ChartArea1").Position.X = 0
            Chart1.ChartAreas("ChartArea1").Position.Width = 100

            Chart1.ChartAreas("ChartArea1").AxisY.Minimum = fromtime.ToOADate
            Chart1.ChartAreas("ChartArea1").AxisY.Maximum = totime.ToOADate
            Chart1.SuspendLayout()

            Dim s As New Series
            s.YValueType = ChartValueType.DateTime
            s.ChartType = SeriesChartType.StackedBar

            For i = UserDT.Rows.Count - 1 To 1 Step -1

                Dim p As New DataPoint

                Dim dr, nextdr As DataRow
                dr = UserDT.Rows(i)
                nextdr = UserDT.Rows(i - 1)

                If nextdr("s").ToString = "R" Then
                    p.Color = Color.Red
                ElseIf nextdr("s").ToString = "Y" Then
                    p.Color = Color.Yellow
                ElseIf nextdr("s").ToString = "G" Then
                    p.Color = Color.LimeGreen
                ElseIf nextdr("s").ToString = "idle" Then
                    p.Color = Color.White
                ElseIf nextdr("s").ToString = "Beaktime_Start" Then
                    p.Color = Color.Blue
                Else
                    p.Color = Color.Gray
                End If


                Dim y As Double

                y = CDate(dr("rectime")).ToOADate
                p.XValue = 1
                p.YValues = {y}
                s.Points.Add(p)

            Next
            Chart1.Series.Add(s)
            Chart1.ResumeLayout()
        Catch ex As Exception

        End Try
    End Sub