开发者

VB.NET DataGridView "An item with the same key has already been added." while using a unique index

VB.NET 2010, .NET 4

Hello,

I've looked around and can't seem to find a solution to my problem. I have an EventLog object which inherits DataGridView and has a public variable EventList which is a List(Of EventLogItem). EventLogItem has seven properties which describe the event, including Index which is set to EventList.Count each time an entry is added (so, it should be unique). Everything has worked just fine until I tried to add an entry from a serial port DataReceived event handler upon which I receive the following exception:

An error occurred creating the form. See Exception.InnerException for details. The error is: An item with the same key has already been added.

Clicking 'View Details' and expanding the InnerException yields no more information. Here is some relevant code:

The EventLog class with its EventList:

Public Class EventLog
    Inherits DataGridView

    Public EventList As New List(Of EventLogItem)

    ..Column creation code, etc..
End Class

The EventLogItem class:

Public Class EventLogItem

    Public Property Index As Integer
    Public Property Timestamp As String
    Public Property User As String = String.Empty
    Public Property [Step] As String = String.Empty
    Public Property Type As Types
    Public Property Message As String
    Public Property TypeIcon As Image

    Public Enum Types
        SeriousError = -2
        NormalError = -1
        Warning = 0
        NormalEvent = 1
        ImportantEvent = 2
        ManualEntry = 3
    End Enum

    Private Sub New()
        Me.Timestamp = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss.f")
        Me.Type = Types.NormalEvent
        SetTypeIcon()
    End Sub
    Public Sub New(ByVal Message As String)
        Me.New()
        Me.Message = Message
    End Sub
    Public Sub New(ByVal Message As String, ByVal User As String)
        Me.New()
        Me.Message = Message
        Me.User = User
    End Sub
    Public Sub New(ByVal Message As String, ByVal User As String, ByVal Type As Types)
        Me.New(Message, User)
        Me.Type = Type
        SetTypeIcon()
    End Sub
    Public Sub New(ByVal Message As String, ByVal User As String, ByVal Type As Types, ByVal [Step] As Integer)
        Me.New(Message, User, Type)
        Me.Step = ([Step] + 1).ToString
    End Sub

    Private Sub SetTypeIcon()
        Select Case Me.Type
            Case Types.NormalError
                Me.TypeIcon = My.Resources.ErrorIcon
            Case Types.SeriousError
                Me.TypeIcon = My.Resources.ErrorIcon
            Case Types.Warning
                Me.TypeIcon = My.Resources.WarningIcon
            Case Types.ManualEntry
                Me.TypeIcon = My.Resources.ManualIcon
            Case Else
                Me.TypeIcon = My.Resources.OkayIcon
        End Select
    End Sub
End Class

Code for inserting an item into the event log:

Inside my main-form class:
    Public Sub NewEventLogEntry(ByVal Message As String, ByVal ex As Exception, ByVal Type As EventLogItem.Types, ByVal IncludeProcessStepNumber As Boolean)
        If IncludeProcessStepNumber Then
            SafeInvokeControl(EventLog, Sub(x)
                                            Dim FirstRow As Integer = x.FirstDisplayedScrollingRowIndex
                                            Dim [Event] As New EventLogItem(Message, My.Settings.SelectedUser, Type, Device.CurrentProcessStep)
         开发者_运维百科                                   [Event].Index = x.RowCount + 1
                                            x.EventList.Insert(0, [Event])
                                            x.DataSource = GetType(List(Of EventLogItem))
                                            x.DataSource = x.EventList
                                            x.SetRowStyles()
                                            If FirstRow >= 0 And FirstRow < x.RowCount Then x.FirstDisplayedScrollingRowIndex = FirstRow
                                        End Sub)
        Else
            SafeInvokeControl(EventLog, Sub(x)
                                            Dim FirstRow As Integer = x.FirstDisplayedScrollingRowIndex
                                            Dim [Event] As New EventLogItem(Message, My.Settings.SelectedUser, Type)
                                            [Event].Index = x.RowCount + 1
                                            x.EventList.Insert(0, [Event])
                                            x.DataSource = GetType(List(Of EventLogItem))
                                            x.DataSource = x.EventList
                                            x.SetRowStyles()
                                            If FirstRow >= 0 And FirstRow < x.RowCount Then x.FirstDisplayedScrollingRowIndex = FirstRow
                                        End Sub)
        End If
        If Type < EventLogItem.Types.Warning Then
            Dim ErrorBox As New ErrorBox
            Dim ErrorBoxThread As New Threading.Thread(AddressOf ErrorBox.ShowDialog)
            ErrorBoxThread.IsBackground = True
            ErrorBox.Exception = ex
            If Type = EventLogItem.Types.NormalError Then
                ErrorBox.Type = ErrorBox.Types.Error
                ErrorBox.Message = Message
            ElseIf Type = EventLogItem.Types.SeriousError Then
                ErrorBox.Type = ErrorBox.Types.SeriousError
                ErrorBox.Message = Message & vbNewLine & vbNewLine & "This is a serious error and indicates that the program is " & _
                    "unstable. The source of this error should be corrected before this program is used for anything important."
            End If
            StopMasterTimer()
            ErrorBoxThread.Start()
        End If
    End Sub
end main-form class snippet

The code that's causing the problem (ch4cp is my namespace. this code resides in a class other than my main-form class):

Inside a serial port device class:
 <Runtime.CompilerServices.MethodImplAttribute(Runtime.CompilerServices.MethodImplOptions.Synchronized)> _
    Private Shared Sub Port_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles Port.DataReceived
        ..some code..
        ch4cp.NewEventLogEntry("testing")
        ..some more code..
    End Sub
End serial port device class snippet

Any ideas?

Thanks a lot in advance.


It sounds like you are getting a thread exception error in your code somewhere. The threading problem will cause other issues and not appear until you step through the code and look at each line being executed.

Try the following at the beginning of your code block to try to identify the problem.

Control.CheckForIllegalCrossThreadCalls = false
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜