1

I am trying to update a DataGridViewCell in my UI form using a thread. Everywhere I have searched over the internet, more or less I found that they are asking to update the data source which is somehow not possible for me to implement in this project due to some restrictions.

A sample code is given below to understand my problem.

I have written a Sub in a module to get the values to be updated in the gridview.

Public Sub GetValues()
    For I as Integer = 0 to N 'N = Row Count of the gridview
        For J as Integer = 0 to M 'M = column count of the gridview
            frmMain.DGV.Rows(I).Cells(J).Value = I * J
        Next
    Next
End Sub

Now I'm trying to create a thread to start the sub GetValues and want that thread to update the cells in my gridview DGV one by one.

Dim T As Threading.Thread = New Threading.Thread(AddressOf Module1.GetValues)
T.Start()

But it's not Working/Updating. Please help

Meghdut Saha
  • 85
  • 1
  • 14
  • Running that code in a background thread won't make anything faster/more responsive as you have to interrupt the UI through `Control.(Begin)Invoke` every time you want to update it. What exactly are you trying to achieve? How many rows and columns does your DGV have? – Visual Vincent Dec 18 '18 at 14:14
  • Approximately I will have less than 3000 rows and the values for each row will be calculated based on a long research work (not as the simple one as illustrated in the sample). All I want is to free the UI from freezing while this long work is going on. – Meghdut Saha Dec 18 '18 at 14:34
  • Also Would like to mention that if the sub is written inside frmMain, then It works but when I am declaring it in another module, it doesn't work. But I have to call it from a module. I am very new to threading, am I missing some basic concept? – Meghdut Saha Dec 18 '18 at 14:44
  • _"am I missing some basic concept?"_ - Yes, namely: _**Leave all UI-related work on the UI thread only**_. Like I said in my previous comment merely putting your code in a thread won't solve anything. If you need to add this large amount of data then you can do two things: – Visual Vincent Dec 18 '18 at 15:03
  • **1)** [Suspend redrawing](https://stackoverflow.com/a/487757) until your code is done updating the UI. This is to prevent the UI from redrawing itself on _every_ "add", which will speed things up a bit (but still the more you add the slower it gets). **2)** Add the items in batches. For instance you can use a [`Timer`](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.timer) that only adds _x_ items every tick. – Visual Vincent Dec 18 '18 at 15:06
  • Alternatively, but also much more advanced, rewrite your code to only show the items that are actually supposed to be visible at the time. || If the calculations for each cell also are time consuming then you might want to mix multithreading with the timer solution (perform the calculations in the background thread, keep letting the timer update the UI in batches). – Visual Vincent Dec 18 '18 at 15:09

2 Answers2

0

With Me.Invoke() or Me.BeginInvoke(). The first updates immediately the second is asynchronous.

Public Sub GetValues()
For I as Integer = 0 to N 'N = Row Count of the gridview
    For J as Integer = 0 to M 'M = column count of the gridview
        Me.BeginInvoke(Sub() frmMain.DGV(J,I).Value = I * J)
    Next
Next
End Sub
CruleD
  • 1,153
  • 2
  • 7
  • 15
  • Getting error: : 'Invoke or BeginInvoke cannot be called on a control until the window handle has been created.' As the code is written in a module, I guess I need to write frmMain.BeginInvoke(Sub() frmMain.DGV(J, I).Value = I * J) because Me is not allowed in a module. – Meghdut Saha Dec 18 '18 at 14:56
  • Like I explained in my comment to the question this will still freeze the UI as it still updates it on every iteration, no matter if you use the asynchronous `BeginInvoke` or not. The UI simply cannot be updated like this if one wants it to stay responsive. – Visual Vincent Dec 18 '18 at 14:58
0

Consider using a BackgroundWorker. It is a thread process and you can make it pause to pass the data from the thread to the main process.

bits
  • 11
  • 2