2011-04-11 164 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