Hi, Bill.
It seems you're doing the same thing again (i. e., updating a control
in a background thead), only now it's the Datagrid.
I suspect that when you call
_ChildForm.Spoc_ev_resultsTableAdapter.Fill(...) from inside the
DoWork method, the update gets blocked, 'cause anything running inside
the DoWork method is in a secondary thread.
As Tom suggested, one way to do what you want could be to use the
ProgressChanged event of the BackgroundWorker (which kicks in on the
main thread) to update the display. In this case, the filling of the
grid should be left in the main thread (as you were originally doing
it seems).
Another approach, as Tom also pointed out, is to use the form's invoke
method. It turns out a control (and the form) has the method
InvokeRequired which returns true if the current thread can't update
the user interface. If so, then you must resort to calling the form's
Invoke method, passing the address of the method to execute and an
array with the method's parameters. Invoke will then ensure that the
method is executed in a thread that can update the UI (usually the
main thread).
As a side note, considering your first example, it seems also you are
acessing, from your secondary thread, a variable which gets data
updated from the main thread (g_bRetreiveDone(g_ChildFormNumber)).
Ideally, all access to variables shared between threads should be
"interlocked". In your case, maybe you don't get into trouble, cause
it seems it's only the main thread that updates the variable, but keep
this in mind for future reference.
Finally, notice that you have a **very tight** loop running inside
UpdateRetrievetimer. I mean, the thing is running *non-stop* probably
hundreds or even thousands of times per second without much need,
since its only job is to update the screen once per second. It would
be nice if you put it to rest at regular intervals, say 500 ms...
Using your original approach as reference, here's a possible (but not
tested, mind you) solution:
<example>
'In the child form
Delegate Sub Updater(Text As String)
Private mFinishUpdate As Boolean
'used to lock shared access to the variable above
Private mLock As New Object
Private Property Finished As Boolean
Get
Dim Result As Boolean
SyncLock(mLock)
Result = mFinished
End SyncLock
Return Result
End Get
Set(Value As Boolean)
SyncLock(mLock)
mFinished = Value
End SyncLock
End Set
End Property
Sub UpdateTimer(Text As String)
Static DoUpdate As Updater = AddressOf UpdateTimer
If Me.InvokeRequired Then
'this runs in the secondary thread
Me.Invoke(DoUpdate, New Object(){Text})
Else
'this runs in the main thread
Me.rssRetrieveTime.Text = Text
End If
End Sub
Public Sub UpdateRetrieveTimer()
Dim ts As TimeSpan
Dim s As String
Do While Not Finished
ts = Date.Now - g_dtStartQuery
s = String.Format("{0:d2}:{1:d2}:{2:d2}", _
ts.Hours, ts.Minutes, ts.Seconds)
UpdateTimer(s)
System.Threading.Thread.Sleep(500)
Loop
End Sub
</example>
Hope this helps.
Regards,
Branco.
------------------