从不同线程 vb.net 更新 BindingList(of T)

Update BindingList(of T) from different thread vb.net

几天前我一直在寻找来自其他线程的 BindingList Invoke,但无法在 vb.net 中找到合适的解决方案,其中大部分是在 C# 中,但我发现很难理解。 因此,我创建了一个小型应用程序,它有 2 个表单(Form1 和 Form2)和一个 Class,Form1 将是主 UI 线程,而 Form2 将是 运行 在另一个线程上。

Form1 有一个 DataGrindView 绑定到共享的 BindingList(of T) 和一个 Button,一旦单击 Button,Form2 将在不同的线程上加载。

这是 Form1 代码:

Imports System.ComponentModel
Imports System.Threading
Public Class Form1
    Public Shared ListOfNames As BindingList(Of Names) = New BindingList(Of Names)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        DataGridView1.DataSource = ListOfNames
        DataGridView1.Columns("FullName").DataPropertyName = "FullName"
    End Sub

    Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
        Dim thread As Threading.Thread = New Threading.Thread(AddressOf loadQuoteForm)
        thread.SetApartmentState((ApartmentState.STA))
        thread.Start()
    End Sub

    Private Sub loadQuoteForm()
        Dim SecondForm As Form2 = New Form2
        Application.Run(SecondForm)
    End Sub
End Class

Form2 只有一个按钮,单击后将创建一个 Names class 实例,更改它的一个 属性 并尝试添加到 Form1.BindingList(of T).

这是 Form2 代码:

Public Class Form2
    Private Sub btnTestFromDiffTread_Click(sender As Object, e As EventArgs) Handles btnTestFromDiffTread.Click
        Try
            Dim myName As Names = New Names
            myName.FullName = "John Peter"
            Form1.ListOfNames.Add(myName)
        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try
    End Sub
End Class


Imports System.ComponentModel
Public Class Names
    Implements System.ComponentModel.INotifyPropertyChanged
    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
    Private _fullName As String
    Public Property FullName() As String
        Get
            Return _fullName
        End Get
        Set(ByVal value As String)
            _fullName = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("FullName"))
        End Set
    End Property
End Class

但是您可能已经猜到,一旦单击 Form2 上的按钮就会抛出异常: .

任何人都可以建议我应该在哪里调用或委托,非常感谢示例 VB.net 代码

引起问题的是 DataGridView 的更新。

从你的评论我可以看出是因为DataGridView绑定到DataGridView的DataSource,所以如果你在一个单独的线程上更新这个List会导致跨线程操作。

一个解决方案是不创建 ListOfNames public 并使用新方法允许添加到此列表:

Private Shared ListOfNames As BindingList(Of Names) = New BindingList(Of Names)

Public Sub AddNameToList(newNames As Names)
    DataGridView1.BeginInvoke(Sub() ListOfNames.Add(newNames))
End Sub

最后,在大家的建议和下面的测试之后,对 Form2 按钮的更改进行了单击,并在 Form1 上添加了一些方法解决了问题:

在 Form1 上添加了方法

Private Shared ListOfNames As BindingList(Of Names) = New BindingList(Of Names)
Private Delegate Sub AddNameToListDelegate(newName As Names)

Public Sub InvokeANDCreateHandle(ByVal newNames As Names)
    Try
        If Me.IsHandleCreated = False Then
            Me.CreateHandle()
        End If
        DataGridView1.Invoke(New AddNameToListDelegate(AddressOf AddNameToList), newNames)
    Catch ex As Exception
        MsgBox(ex.ToString)
    End Try
End Sub

Private Sub AddNameToList(name As Names)
    ListOfNames.Add(name)
End Sub

并将点击 From2 的按钮更改为:

 Private Sub btnTestFromDiffTread_Click(sender As Object, e As EventArgs) Handles btnTestFromDiffTread.Click
    Try
        Dim myName As Names = New Names
        myName.FullName = "John Peter"
        Form1.InvokeANDCreateHandle(myName)
    Catch ex As Exception
        MsgBox(ex.ToString)
    End Try
 End Sub