Cross-thread operation not valid

匿名 (未验证) 提交于 2019-12-03 01:29:01

问题:

I was doing the following to try out threadings but get the 'Cross-Threading' error in the line txtBox.Text = DataGridView2.Rows.Item(iloop).Cells(3).Value, anyone can point out what's wrong, thanks:

Dim lm As New Thread(AddressOf load_movie)         Dim lt As New Thread(AddressOf load_timings)         lm.Start()         lt.Start()  Private Sub load_movie()          For iloop As Integer = 0 To DataGridView1.Rows.Count - 2             Dim Cstring As String = "txt_Movie_0" & iloop.ToString             For Each cCtrl As Control In Panel1.Controls                 If TypeOf cCtrl Is TextBox Then                     Dim txtBox As TextBox                     txtBox = cCtrl                     If txtBox.Name = Cstring Then                         txtBox.Text = DataGridView1.Rows.Item(iloop).Cells(1).Value                     End If                 End If             Next         Next     End Sub      Private Sub load_timings()         For iloop As Integer = 0 To DataGridView2.Rows.Count - 2             For Each cCtrl As Control In Panel2.Controls                 If TypeOf cCtrl Is TextBox Then                     Dim txtBox As TextBox                     txtBox = cCtrl                     If (txtBox.Name.Substring(9, 6)) = (DataGridView2.Rows.Item(iloop).Cells(0).Value.substring(0, 6)) Then                         txtBox.Text = DataGridView2.Rows.Item(iloop).Cells(3).Value 'This is the part that says "Cross-thread operation not valid: Control 'txt_Time_00_000' accessed from a thread other than the thread it was created on."                     End If                 End If             Next         Next      End Sub 

回答1:

@JaredPar you have the basic idea but that code itself won't compile (unless I'm missing something). For VB9 or less you need to declare an actual delegate and invoke that:

    ''//The delegate is only needed for the VB 9 or less version     Private Delegate Sub UpdateTextBoxDelegate(ByVal txtBox As TextBox, ByVal value As String)      If TypeOf cCtrl Is TextBox Then         Dim txtBox As TextBox         txtBox = cCtrl         ''//Perform validation logic here         If (txtBox.Name.Substring(9, 6)) = (DataGridView2.Rows.Item(iloop).Cells(0).Value.ToString().Substring(0, 6)) Then             ''//Call the update method with our textbox and value             UpdateTextBox(txtBox, DataGridView2.Rows.Item(iloop).Cells(3).Value.ToString())         End If     End If      Private Sub UpdateTextBox(ByVal txtBox As TextBox, ByVal value As String)         ''//Basically ask the textbox if we need to invoke         If txtBox.InvokeRequired Then             ''//For VB 9 or less you need a delegate             txtBox.Invoke(New UpdateTextBoxDelegate(AddressOf UpdateTextBox), txtBox, value)         Else             txtBox.Text = value         End If     End Sub 

For VB 10 we can finally use anonymous subs so we can completely get rid of the delegate:

    If TypeOf cCtrl Is TextBox Then         Dim txtBox As TextBox         txtBox = cCtrl         ''//Perform validation logic here         If (txtBox.Name.Substring(9, 6)) = (DataGridView2.Rows.Item(iloop).Cells(0).Value.ToString().Substring(0, 6)) Then             ''//Call the update method with our textbox and value             UpdateTextBox(txtBox, DataGridView2.Rows.Item(iloop).Cells(3).Value.ToString())         End If     End If  Private Sub UpdateTextBox(ByVal txtBox As TextBox, ByVal value As String)     If txtBox.InvokeRequired Then         ''//For VB 10 you can use an anonymous sub         txtBox.Invoke(Sub() UpdateTextBox(txtBox, value))     Else         txtBox.Text = value     End If End Sub 


回答2:

It's not legal to access a UI element from anything other than UI thread in .Net code. Hence when you try and use the DataGridView2 instance from a background thread it rightfully throws an exception.

In order to read or write to a UI component you need to use Invoke or BeginInvoke method to get back on the UI thread and make the update. For example

If TypeOf cCtrl Is TextBox Then     Dim txtBox As TextBox     txtBox = cCtrl     txtBox.Invoke(AddressOf UpdateTextBox, txtBox, iloop) End If  Private Sub UpdateTextBox(txtBox as TextBox, iloop as Integer)      If (txtBox.Name.Substring(9, 6)) = (DataGridView2.Rows.Item(iloop).Cells(0).Value.substring(0, 6)) Then         txtBox.Text = DataGridView2.Rows.Item(iloop).Cells(3).Value 'This is the part that says "Cross-thread operation not valid: Control 'txt_Time_00_000' accessed from a thread other than the thread it was created on."     End If End Sub 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!