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

时间:2016-07-15 14:03:44

标签: c# vb.net multithreading bindinglist

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

Form1有一个DataGrindView绑定到共享BindingList(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类实例,更改其一个属性并尝试添加到Form1.BindingList(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上单击按钮就会抛出异常: enter image description here

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

2 个答案:

答案 0 :(得分:1)

正在更新引起问题的DataGridView。

从您的评论中我可以看到它是因为DataGridView绑定到DataGridView的DataSource,因此如果您在单独的线程上执行此操作,更新此List将导致跨线程操作。

一种解决方案是不公开ListOfNames并使用新方法来添加此列表:

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

答案 1 :(得分:0)

最后,在每个人的建议和测试下面的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