我几天前一直在寻找其他线程的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上单击按钮就会抛出异常:
任何人都可以建议我应该调用或委托的地方,非常感谢示例VB.net代码
答案 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