Shabeer Shabeer - 4 months ago 47
Vb.net Question

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

I have been looking for BindingList Invoke from other thread few days ago but not able to get a proper solution in vb.net , most of them are in C# but i am finding difficult to understand that.
Hence i have created a small application which has 2 Forms (Form1 and Form2) and one Class, Form1 will be main UI thread and Form2 will be running on a different thread.

Form1 has a DataGrindView bound to shared BindingList(of T) and a Button, once the Button clicked Form2 will be loaded on a different thread.

Here is Form1 Codes :

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 just has a button, once clicked will create a Names class instance , change its one property and try to add to Form1.BindingList(of T).

Here is Form2 Codes:

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


but as you may have guessed as soon as button clicked on Form2 throws exception :
enter image description here
.

Can anyone please suggest where i should invoke or delegate , sample VB.net codes are very much appreciated

Answer

It is updating of the DataGridView that is causing the issue.

From your comment I can see it is because the DataGridView is bound to DataSource of the DataGridView, so updating this List will cause a cross thread operation if you are doing this on a separate thread.

One solution is to not make ListOfNames public and have a new method to allow adding to this list:

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