可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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