none
How can I add rows to a datagridview using a background worker?

    Question

  • Hi, I want to thank everyone in advance for any help you can offer.  I am an amateur programmer and I have been able to turn to this forum repeatedly for help with my problems --- and this is deeply appreciated by me!   Thank you!

    I want to load a .csv file into a datagridview.  The .csv file has 10 columns and at least 70,000 to 100,000 rows.  When the program loads the file, the whole program freezes for several minutes.  I eventually figured out that I could use a background worker to do things.  However, when I tried to have the background worker add rows to the datagridview, I got an error message saying that it couldn't because the datagridview was created on another thread than its own.  .... I am wondering how I can solve this issue?  Here is the program: 

    Public Class Form1
    
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
    BackgroundWorker1.RunWorkerAsync()
    
    End sub
    
    Private Sub bw() Handles BackgroundWorker1.DoWork
    
    get_main_catalog_of_items()
    
    end sub
    
       Private Sub get_main_catalog_of_items()
            Datagridview1.Rows.Clear()
            Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("c:\catalogs\catalog_main.csv")
                MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
                MyReader.Delimiters = New String() {vbTab}
                Dim currentRow As Strng()
                While Not MyReader.EndOfData
                    Try
                        currentRow = MyReader.ReadFields()
                        DataGridView1.Rows.Add(currentRow)
                    Catch ex As Exception
                    End Try
                End While
            End Using
        End Sub

    I hope you can help me!  Thank you!


    Thursday, October 09, 2014 9:47 PM

Answers

  • Basically, what is happening is that when you access an object on one thread from another thread, this creates an unstable system environment. The way for getting around this is to check and see if an invoke is required for that object, and basically, if it is, you invoke a new delegate sub on the same thread of the datagridview, hence avoiding access across threads, because the delegate sub exists on the same thread as the datagridview. See example

    Example

    Option Strict On
    Option Explicit On
    Option Infer Off
    Public Class Form1
        Dim bgw As New System.ComponentModel.BackgroundWorker
        Private Delegate Sub addDGVRow(dgv As DataGridView, row As DataGridViewRow)
        Sub doRowAdd(dgv As DataGridView, row As DataGridViewRow)
            If dgv.InvokeRequired Then
                dgv.Invoke(New addDGVRow(AddressOf doRowAdd), dgv, row)
            Else
                dgv.Rows.Add(row)
            End If
        End Sub
        Sub work(sender As Object, e As EventArgs)
            For i As Integer = 0 To 1000
                Dim row As New DataGridViewRow
                row.Cells.Add(New DataGridViewTextBoxCell With {.Value = i.ToString})
                row.Cells.Add(New DataGridViewTextBoxCell With {.Value = (i + 1).ToString})
                doRowAdd(DataGridView1, row)
            Next
        End Sub
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            DataGridView1.ColumnCount = 2
            AddHandler bgw.DoWork, AddressOf work
            bgw.RunWorkerAsync()
        End Sub
    End Class
    See the solution applied to your exact problem here


    “If you want something you've never had, you need to do something you've never done.”

    Don't forget to mark helpful posts and answers ! Answer an interesting question? Write a new article about it! My Articles
    *This post does not reflect the opinion of Microsoft, or its employees.




    Thursday, October 09, 2014 10:44 PM
    Moderator

All replies

  • Basically, what is happening is that when you access an object on one thread from another thread, this creates an unstable system environment. The way for getting around this is to check and see if an invoke is required for that object, and basically, if it is, you invoke a new delegate sub on the same thread of the datagridview, hence avoiding access across threads, because the delegate sub exists on the same thread as the datagridview. See example

    Example

    Option Strict On
    Option Explicit On
    Option Infer Off
    Public Class Form1
        Dim bgw As New System.ComponentModel.BackgroundWorker
        Private Delegate Sub addDGVRow(dgv As DataGridView, row As DataGridViewRow)
        Sub doRowAdd(dgv As DataGridView, row As DataGridViewRow)
            If dgv.InvokeRequired Then
                dgv.Invoke(New addDGVRow(AddressOf doRowAdd), dgv, row)
            Else
                dgv.Rows.Add(row)
            End If
        End Sub
        Sub work(sender As Object, e As EventArgs)
            For i As Integer = 0 To 1000
                Dim row As New DataGridViewRow
                row.Cells.Add(New DataGridViewTextBoxCell With {.Value = i.ToString})
                row.Cells.Add(New DataGridViewTextBoxCell With {.Value = (i + 1).ToString})
                doRowAdd(DataGridView1, row)
            Next
        End Sub
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            DataGridView1.ColumnCount = 2
            AddHandler bgw.DoWork, AddressOf work
            bgw.RunWorkerAsync()
        End Sub
    End Class
    See the solution applied to your exact problem here


    “If you want something you've never had, you need to do something you've never done.”

    Don't forget to mark helpful posts and answers ! Answer an interesting question? Write a new article about it! My Articles
    *This post does not reflect the opinion of Microsoft, or its employees.




    Thursday, October 09, 2014 10:44 PM
    Moderator
  • Thanks so much for your time!  I will work to apply your solution to my program.  That was very kind and generous of you to help me!
    Monday, October 13, 2014 4:02 PM
  • I was curious which one would win the race

    Option Strict On
    Public Class Form1
        Dim bgw As New System.ComponentModel.BackgroundWorker
        Private Delegate Sub addDGVRow(dgv As DataGridView, row As DataGridViewRow)
        Sub doRowAdd(dgv As DataGridView, row As DataGridViewRow)
            If dgv.InvokeRequired Then
                dgv.Invoke(New addDGVRow(AddressOf doRowAdd), dgv, row)
            Else
                dgv.Rows.Add(row)
            End If
        End Sub
        Sub work(sender As Object, e As EventArgs)
            For i As Integer = 0 To 1000
                Dim row As New DataGridViewRow
                row.Cells.Add(New DataGridViewTextBoxCell With {.Value = i.ToString})
                row.Cells.Add(New DataGridViewTextBoxCell With {.Value = (i + 1).ToString})
                doRowAdd(DataGridView1, row)
            Next
        End Sub
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            DataGridView1.ColumnCount = 2
            DataGridView2.ColumnCount = 2
            AddHandler bgw.DoWork, AddressOf work
            bgw.RunWorkerAsync()
            DataGridView2.SuspendLayout()
            For i As Integer = 0 To 1000
                Dim row As New DataGridViewRow
                row.Cells.Add(New DataGridViewTextBoxCell With {.Value = i.ToString})
                row.Cells.Add(New DataGridViewTextBoxCell With {.Value = (i + 1).ToString})
                DataGridView2.Rows.Add(row)
            Next
            DataGridView2.ResumeLayout()
            DataGridView2.CurrentCell = DataGridView2.Rows(999).Cells(0)
        End Sub
    End Class
    


    Success
    Cor

    Monday, October 13, 2014 5:18 PM
  • Thanks so much for your time!  I will work to apply your solution to my program.  That was very kind and generous of you to help me!
    You're welcome

    “If you want something you've never had, you need to do something you've never done.”

    Don't forget to mark helpful posts and answers ! Answer an interesting question? Write a new article about it! My Articles
    *This post does not reflect the opinion of Microsoft, or its employees.

    Monday, October 13, 2014 5:27 PM
    Moderator