2011-04-11 120 views
2

我在做以下尝试螺纹,但在该行txtBox.Text = DataGridView2.Rows.Item(iloop).Cells(3).Value得到了“跨线程”的错误,任何人都可以点出了什么问题,谢谢:跨线程操作无效

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 

回答

3

@JaredPar你有基本的想法,但代码本身不会编译(除非我失去了一些东西)。对于VB9或更低,你需要声明一个实际的委托并调用是:

''//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 

对于VB 10,我们终于可以用匿名的潜艇,所以我们可以完全摆脱对受委托者:

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 
4

这不是合法的从.Net代码中的UI线程以外的其他任何东西访问UI元素。因此,当您尝试从后台线程使用DataGridView2实例时,它会正确引发异常。

为了读取或写入UI组件,您需要使用InvokeBeginInvoke方法取回UI线程并进行更新。例如

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