Moin,
ich habe ein Datagridview das auflaufende Fehler anzeigen soll und dazu habe ich sie mit einer Datatable verbunden in der ich die Datanaktualisiere bzw. hinzufüge und lösche.
In einem Thread wird im hintergrund die ganze Zeit gelesen und der aktualisiert die Datatable.
Ich habe mir jetzt ein Textprogramm geschrieben, um mein Programm kaputt zu bekommen und hab es leider geschafft. Ab und zu wird die Meldung "System.IndexOutOfRangeException" generiert.
So im ganzen:
2022-08-25 17:18:11,503 [1] ERROR QSorting - System.IndexOutOfRangeException: Der Index 15 hat keinen Wert.
bei System.Windows.Forms.CurrencyManager.get_Item(Int32 index)
bei System.Windows.Forms.DataGridView.DataGridViewDataConnection.GetError(Int32 rowIndex) -- System.Windows.Forms.DataGridView.OnDataErrorInternal > System.Windows.Forms.DataGridView.OnDataError > QSorting.Alarmbox.Alarmbox_DataError
Da ich zuerst der Meinung war, dass es am Hintergrundthread liegt, habe ich mehere Syncmethoden eingebaut, die alle keinen Erfolg hatten. Es kann meines Erachtens auch nicht schuld sein, weil nur der Thread schreiben schreibt und löscht, kein 2. oder 3.
So habe ich meine Datagridview erstellt:
Und so habe ich meine Datatable erstellt:
In der Datatable benutze ich die Funktion Update, um die Daten hinzuzufügen oder zu entfernen.
Da der Fehler sporadisch ist, weiß ich nicht mal wie ich den provoziere und wieso er versucht wird.
Google bringt mich momentan nicht weiter und ansonst läuft das Programm komplett stabil.
Kann mir einer das Phaenomen erklären oder mir sagen was ich übersehe?
Ich frage ja extra ab, ob es die Zeile in der Tabelle gibt und trotzdem kommt der Fehler
Viele Grüße
ich habe ein Datagridview das auflaufende Fehler anzeigen soll und dazu habe ich sie mit einer Datatable verbunden in der ich die Datanaktualisiere bzw. hinzufüge und lösche.
In einem Thread wird im hintergrund die ganze Zeit gelesen und der aktualisiert die Datatable.
Ich habe mir jetzt ein Textprogramm geschrieben, um mein Programm kaputt zu bekommen und hab es leider geschafft. Ab und zu wird die Meldung "System.IndexOutOfRangeException" generiert.
So im ganzen:
2022-08-25 17:18:11,503 [1] ERROR QSorting - System.IndexOutOfRangeException: Der Index 15 hat keinen Wert.
bei System.Windows.Forms.CurrencyManager.get_Item(Int32 index)
bei System.Windows.Forms.DataGridView.DataGridViewDataConnection.GetError(Int32 rowIndex) -- System.Windows.Forms.DataGridView.OnDataErrorInternal > System.Windows.Forms.DataGridView.OnDataError > QSorting.Alarmbox.Alarmbox_DataError
Da ich zuerst der Meinung war, dass es am Hintergrundthread liegt, habe ich mehere Syncmethoden eingebaut, die alle keinen Erfolg hatten. Es kann meines Erachtens auch nicht schuld sein, weil nur der Thread schreiben schreibt und löscht, kein 2. oder 3.
So habe ich meine Datagridview erstellt:
VB.NET-Quellcode
- Public Class Alarmbox
- Inherits DataGridView
- Sub New() 'ByRef Alarmtable As Alarmboxdatatable)
- Try
- 'Nicht zur Designzeit ausfuehren:
- If System.ComponentModel.LicenseManager.UsageMode = System.ComponentModel.LicenseUsageMode.Designtime Then Return
- ' Dieser Aufruf ist für den Designer erforderlich.
- InitializeComponent()
- 'Werte aus der Einstellung uebernehmen
- Me.Columns.Clear()
- DataGridSettings()
- Me.DoubleBuffered = True
- RemoveHandler MyBase.Resize, AddressOf Alarmbox_Resize
- AddHandler MyBase.Resize, AddressOf Alarmbox_Resize
- Catch ex As Exception
- Log.Error(ex)
- End Try
- End Sub
- Private Sub DataGridSettings()
- Try
- 'Einstellung vom Datagrid:
- Me.BackgroundColor = Color.Gray
- 'Set the selection background color for all the cells.
- Me.DefaultCellStyle.SelectionBackColor = Color.Red
- Me.DefaultCellStyle.SelectionForeColor = Color.White
- Me.RowsDefaultCellStyle.BackColor = Color.Red
- Me.RowsDefaultCellStyle.ForeColor = Color.White
- 'Alternating:
- 'Me.AlternatingRowsDefaultCellStyle.BackColor = Color.DarkGray
- Me.AllowUserToAddRows = False
- Me.AllowUserToDeleteRows = False
- Me.AllowUserToOrderColumns = True
- Me.ReadOnly = True
- Me.SelectionMode = DataGridViewSelectionMode.FullRowSelect
- Me.MultiSelect = False
- Me.RowHeadersVisible = False
- Me.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells
- Me.AllowUserToResizeColumns = False
- Me.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
- Me.AllowUserToResizeRows = False
- Me.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing
- Catch ex As Exception
- Log.Error(ex)
- End Try
- End Sub
- Private Sub Alarmbox_Resize(sender As Object, e As EventArgs) 'Handles MyBase.Resize
- Try
- ResizeColumns()
- Catch ex As Exception
- Log.Error(ex)
- End Try
- End Sub
- Public Sub ResizeColumns()
- Try
- If Me IsNot Nothing Then
- If Me.InvokeRequired Then
- Return
- End If
- If Me.Columns.Count < 3 Then Return
- Dim Gridwidth = Me.Width
- Me.Columns(0).Width = CInt(Gridwidth * 0.2) - 7
- Me.Columns(1).Width = CInt(Gridwidth * 0.2) - 7
- Me.Columns(2).Width = CInt(Gridwidth * 0.6) - 7
- Me.VerticalScrollBar.Visible = False
- Me.Refresh()
- End If
- Catch ex As Exception
- Log.Error(ex)
- End Try
- End Sub
- Private Sub Alarmbox_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs) Handles MyBase.DataBindingComplete
- Try
- Me.Columns(3).Visible = False
- RemoveHandler MyBase.DataBindingComplete, AddressOf Alarmbox_DataBindingComplete
- Catch ex As Exception
- Log.Error(ex)
- Log.Info("Fehler bei Alarmbox_DataBindingComplete")
- End Try
- End Sub
- Private Sub Alarmbox_DataError(ByVal sender As Object, ByVal e As DataGridViewDataErrorEventArgs) Handles Me.DataError
- Log.Error(e.Exception)
- ShowError(e.Exception)
- End Sub
- End Class
Und so habe ich meine Datatable erstellt:
VB.NET-Quellcode
- Public Class Alarmboxdatatable
- Inherits DataTable
- Private semi As New Semaphore(1, 1)
- Private _Alarmbox As Alarmbox
- Public Structure _Alarmrow
- Dim Datetime As DateTime
- Dim Group As String
- Dim Alarmtext As String
- End Structure
- Private _Alarmdic As New Dictionary(Of Integer, _Alarmrow)
- Sub New(ByRef Alarmbox As Alarmbox)
- Dim Lang As String = My.Settings.Language
- If Lang = "en" Then
- Me.Columns.Add("Time", GetType(DateTime))
- Me.Columns.Add("Group", GetType(String))
- Me.Columns.Add("Alarmtext", GetType(String))
- Me.Columns.Add("ID", GetType(Integer))
- Me.PrimaryKey = New DataColumn() {Me.Columns("ID")}
- Else
- Me.Columns.Add("Zeit", GetType(DateTime))
- Me.Columns.Add("Gruppe", GetType(String))
- Me.Columns.Add("Alarmtext", GetType(String))
- Me.Columns.Add("ID", GetType(Integer))
- Me.PrimaryKey = New DataColumn() {Me.Columns("ID")}
- End If
- _Alarmbox = Alarmbox
- End Sub
- 'Public Property Alarmdic As Dictionary(Of Integer, _Alarmrow)
- 'Set(value As Dictionary(Of Integer, _Alarmrow))
- '_Alarmdic = value
- 'End Set
- 'Get
- 'Return _Alarmdic
- 'End Get
- 'End Property
- <MethodImpl(MethodImplOptions.Synchronized)>
- Friend Sub updateAlarmtabe(ID As Integer, Time As DateTime, Group As String, Alarmtext As String, Value As Boolean) ' As Alarmboxdatatable
- If _Alarmbox Is Nothing Then Exit Sub
- Dim DeliResume As New AlarmResumeDelegate(AddressOf AlarmResume)
- Dim DeliSuspent As New AlarmSuspendDelegate(AddressOf AlarmSuspendLayout)
- semi.WaitOne()
- _Alarmbox.Invoke(DeliSuspent)
- Try
- If Value Then
- If _Alarmdic.ContainsKey(ID) Then
- 'nichts
- Else
- Try
- Dim newRow = Me.NewRow
- newRow.Item(0) = Time
- newRow.Item(1) = Group
- newRow.Item(2) = Alarmtext
- newRow.Item(3) = ID
- Me.Rows.InsertAt(newRow, 0)
- _Alarmdic.Add(ID, New _Alarmrow With {.Datetime = Time, .Group = Group, .Alarmtext = Alarmtext})
- Catch ex As Exception
- Log.Error(ex)
- ' ShowError(ex)
- End Try
- End If
- Else
- If Not _Alarmdic.ContainsKey(ID) Then
- 'nichts
- Else
- Try
- If Me.Rows.Count >= 0 Then
- SyncLock Me
- _Alarmdic.Remove(ID)
- For i = 0 To (Me.Rows.Count - 1)
- If CInt(Me.Rows(i)(3)) = ID Then
- Try
- If Me.Rows.Count >= i AndAlso Me.Rows.Contains(ID) Then Me.Rows.RemoveAt(i)
- Catch ex As Exception
- Log.Error(ex)
- End Try
- Exit For
- End If
- Next
- End SyncLock
- Else
- MessageBox.Show("Row count kleiner gleich null")
- End If
- Catch ex As Exception
- Log.Error(ex)
- ' ShowError(ex)
- End Try
- End If
- End If
- Catch ex As Exception
- Log.Error(ex)
- ' ShowError(ex)
- Finally
- _Alarmbox.Invoke(DeliResume)
- semi.Release()
- End Try
- End Sub
- Private Delegate Sub AlarmRefreshDelegate()
- Private Sub AlarmRefresh()
- _Alarmbox.ResizeColumns()
- End Sub
- Private Delegate Sub AlarmResumeDelegate()
- Private Sub AlarmResume()
- _Alarmbox.ResumeLayout()
- End Sub
- Private Delegate Sub AlarmSuspendDelegate()
- Private Sub AlarmSuspendLayout()
- _Alarmbox.SuspendLayout()
- End Sub
- End Class
In der Datatable benutze ich die Funktion Update, um die Daten hinzuzufügen oder zu entfernen.
Da der Fehler sporadisch ist, weiß ich nicht mal wie ich den provoziere und wieso er versucht wird.
Google bringt mich momentan nicht weiter und ansonst läuft das Programm komplett stabil.
Kann mir einer das Phaenomen erklären oder mir sagen was ich übersehe?
Ich frage ja extra ab, ob es die Zeile in der Tabelle gibt und trotzdem kommt der Fehler
Viele Grüße