"Cross-thread operation not valid: Control 'DataGridView1' accessed from a thread other than the thread it was created on."

I've been avoiding multithreading because of this since I started with vb.net a couple of weeks ago but it looks like I have to start using it now. I simply don't understand this error at all. Microsoft tries to exlain it here, but I simply don't get it; http://msdn.microsoft.com/en-us/library/ms171728.aspx

My code;

Dim t As Thread = New Thread(AddressOf Me.gogogo)

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        connectioninforeplace()
        t.IsBackground = True
        t.Start()
    End Sub

    Public Sub gogogo()
        For lulz As Integer = 0 To 300000
            If TextBox2.Text <= 24356 Then
                'Write
                Dim sr2 As New StringReader("")
                Dim FILE_NAME2 As String = apppath & "\fixit\database.sql"

                If System.IO.File.Exists(FILE_NAME2) = True Then
                    Dim objWriter As New System.IO.StreamWriter(FILE_NAME2)
                    While sr2.Peek <> -1
                        Dim s As String = sr2.ReadLine
                        objWriter.WriteLine(s)
                    End While
                    objWriter.Close()
                    objWriter.Dispose()
                Else
                    MsgBox("File Does Not Exist")
                End If

                Dim querystringdone As String
                querystringdone = "SELECT ID, post_content FROM wp_posts ORDER by ID asc LIMIT 200 OFFSET " & TextBox2.Text & ""
                Dim query As String = querystringdone

                Dim connection As New MySqlConnection(connStr)
                Dim da As New MySqlDataAdapter(query, connection)
                'da.SelectCommand.CommandTimeout = 1200000
                Dim ds As New DataSet()

                da.Fill(ds)
                DataGridView1.DataSource = ds.Tables(0)
                DataGridView1.Refresh()
                connection.Close()
                connection.Dispose()

                TextBox1.Text = "Rows: " & DataGridView1.Rows.Count - 1
                TextBox1.Refresh()

                Dim newsqlthing As String = ""
                For intX As Integer = 0 To DataGridView1.Rows.Count - 2
                    Dim contentfix As String
                    Dim contentfix2 As String
                    contentfix = DataGridView1.Rows(intX).Cells(1).Value
                    contentfix2 = contentfix.Replace("</PRE><!-- END TEMPLATE: bbcode_code -->", "</P>")
                    contentfix2 = Regex.Replace(contentfix2, "PRE style=" & Chr(34) & "HEIGHT: (.*?)" & Chr(34), "P")
                    contentfix2 = contentfix2.Replace("'", "''")
                    contentfix2 = contentfix2.Replace(Chr(34), "\" & Chr(34))
                    If Not intX = DataGridView1.Rows.Count - 2 Then
                        newsqlthing = newsqlthing & vbCrLf & "UPDATE wp_posts SET post_content = '" & contentfix2 & "' WHERE ID = " & DataGridView1.Rows(intX).Cells(0).Value & "; "
                    Else
                        newsqlthing = newsqlthing & vbCrLf & "UPDATE wp_posts SET post_content = '" & contentfix2 & "' WHERE ID = " & DataGridView1.Rows(intX).Cells(0).Value & " "
                    End If


                Next

                'Read database file
                'Dim fileReader As String
                'fileReader = My.Computer.FileSystem.ReadAllText(apppath & "\fixit\database.sql")

                'Write
                Dim sr As New StringReader(newsqlthing)
                Dim FILE_NAME As String = apppath & "\fixit\database.sql"

                If System.IO.File.Exists(FILE_NAME) = True Then
                    Dim objWriter As New System.IO.StreamWriter(FILE_NAME)
                    While sr.Peek <> -1
                        Dim s As String = sr.ReadLine
                        objWriter.WriteLine(s)
                    End While
                    objWriter.Close()
                    objWriter.Dispose()
                Else
                    MsgBox("File Does Not Exist")
                End If

                updateRecord(My.Computer.FileSystem.ReadAllText(apppath & "\fixit\database.sql"))
                DataGridView1.DataSource = Nothing
                DataGridView1.Rows.Clear()
                newsqlthing = ""
                newsqlthing = Nothing
                ds = Nothing
                TextBox2.Text = TextBox2.Text + 200
                TextBox2.Refresh()

            Else
                Me.Close()
            End If
        Next
    End Sub

    Public Function midReturn(ByVal first As String, ByVal last As String, ByVal total As String) As String
        If last.Length < 1 Then
            midReturn = total.Substring(total.IndexOf(first))
        End If
        If first.Length < 1 Then
            midReturn = total.Substring(0, (total.IndexOf(last)))
        End If
        Try
            midReturn = ((total.Substring(total.IndexOf(first), (total.IndexOf(last) - total.IndexOf(first)))).Replace(first, "")).Replace(last, "")
        Catch ArgumentOutOfRangeException As Exception
        End Try
    End Function

Exception is thrown here; (line 38)

DataGridView1.DataSource = ds.Tables(0)

I'm trying to understand how to solve it but I just don't get it :<

Recommended Answers

All 4 Replies

Place this line of code in your Form's .Load event.

Control.CheckForIllegalCrossThreadCalls = False '// allow cross threading.

Thanks, tried that already but for some reason that places a big red X over my DataGridView.

Being late night here, I actually wondered what a big red X looks like painted over a DataGridView. :D

I have used this in the past for Threading and it solved the issue.

Public Sub gogogo()
        If Me.InvokeRequired Then
            Me.Invoke(New MethodInvoker(AddressOf gogogo))
        Else
            '// your code here.
        End If
    End Sub

More info located here.

Well... the error message says it all... since forms are created on separate threads aswell you tried to access your control from another thread... Best way around this is to put your datagridview update in another sub or function apart from your 2nd thread and to invoke it by itself when needed (automatic in a way) but you'll need to declare delegates and a global variable declared as a delegate.

i.e.:

#Region "global variables"
    Delegate Sub updateDataGridDelegate(ByVal param1 As String, ByVal param2 As String)
    Public updateDataG As updateDataGridDelegate
#End Region

    'sub that updates datagridview on main thread:
    Public Sub updateDataGrid(ByVal param1 As String, ByVal param2 As String)
        If Me.InvokeRequired Then
            updateDataG = New updateDataGridDelegate(AddressOf updateDataGrid)
            Me.BeginInvoke(updateDataG, New Object() {param1, param2})
        Else
            '//update DataGrid code here//
        End If
    End Sub

When u need to update your DataGridView inside the 2nd thread u just call:

Dim test1 As String = "some parameter 1"
    Dim test2 As String = "some parameter 2"

    updateDataGrid(test1,test2)
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.