JeffvClayton
asked on
Thread Safe Calls
I have a progress bar set to marquee on an mdi parent status bar. To make it run smoothly and continuously while updating I thought it may be time to try somehting new rather than Application.DoEvents.
So I have a procedure in a child form which is called by the following
....enable the progress bar
Dim newthread As New Threading.Thread(AddressOf MyProcedure)
newthread.Start()
The procedure fills a datatable from various tables, then a DataView which is sorted, which is then used to populate a DataGridView control. I have found out that (via debug message) I have to check the DataGridView.InvokeRequire d property when i try to set the DataGridView datasource, and then do something else if the answer is True, when doing something to a control not invoked by the same thread. I am not sure what code I need if the answer is true.
so..
Private Sub MyProcedure()
....do some stuff
If MyDataGridView.InvokeRequi red Then
......WHAT GOES HERE
else
MyDataGridView.DataSource = MyDataView
End If
'Disable progress bar
me.cursor = cursors.default
MyMdiParent.ProgressBar.En abled=fals e
PS. I have also discovered i will get the same problem when i try to reset the cursor for the form back to default and also try to disable the progress bar as they were set on different threads
End Sub
I am assuming of course this is the way to go for smoothly operating progress bars
So I have a procedure in a child form which is called by the following
....enable the progress bar
Dim newthread As New Threading.Thread(AddressOf
newthread.Start()
The procedure fills a datatable from various tables, then a DataView which is sorted, which is then used to populate a DataGridView control. I have found out that (via debug message) I have to check the DataGridView.InvokeRequire
so..
Private Sub MyProcedure()
....do some stuff
If MyDataGridView.InvokeRequi
......WHAT GOES HERE
else
MyDataGridView.DataSource = MyDataView
End If
'Disable progress bar
me.cursor = cursors.default
MyMdiParent.ProgressBar.En
PS. I have also discovered i will get the same problem when i try to reset the cursor for the form back to default and also try to disable the progress bar as they were set on different threads
End Sub
I am assuming of course this is the way to go for smoothly operating progress bars
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I'm not sure about the "invokerequired" property. You can try creating a progress bar at runtime and accessing it from the thread.
ASKER
OK, that is something to try.
I have also tried this as the last line in the procedure with no error messages, but no data in the DataGridView either!
MyDataGridView.Invoke(MyDa taGridView .DataSourc e, MyDataView.ToTable)
I have also tried this as the last line in the procedure with no error messages, but no data in the DataGridView either!
MyDataGridView.Invoke(MyDa
Sorry, in the earlier post I meant create a progress bar at design time, not runtime
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I have solved the problem, you cant change an object from a different thread, you need all this....
Instead of 'MyDataGridView.DataSource = MyDataView' as the last line of the procedure in the new thread
you need a new procedure call as the last line e.g. PassNewDataView(MyDataView .ToTable)
End Sub
'Another sub which runs in the new thread
'------------------------- ---------- ---------- -----
Sub PassNewDataView(ByVal MyDataView As DataTable)
Me.BeginInvoke(New DelegateUpdateSource(Addre ssOf Me.ChangeSource), New Object() {MyDataView})
End Sub
' then a new Delegate Sub as this....
' -------------------------- ---------- ----
Public Delegate Sub DelegateUpdateSource(ByVal DV As DataTable)
'Finally a sub which runs in the original thread to change the datasource and stop the progress bar
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- --------
Sub ChangeSource(ByVal DV As DataTable)
Me.MyDataGridView.DataSour ce = DV
Me.Cursor = Cursors.Default
MParent.PB1.Enabled = False
End Sub
Thanks anyway
Jeff
Instead of 'MyDataGridView.DataSource
you need a new procedure call as the last line e.g. PassNewDataView(MyDataView
End Sub
'Another sub which runs in the new thread
'-------------------------
Sub PassNewDataView(ByVal MyDataView As DataTable)
Me.BeginInvoke(New DelegateUpdateSource(Addre
End Sub
' then a new Delegate Sub as this....
' --------------------------
Public Delegate Sub DelegateUpdateSource(ByVal
'Finally a sub which runs in the original thread to change the datasource and stop the progress bar
'-------------------------
Sub ChangeSource(ByVal DV As DataTable)
Me.MyDataGridView.DataSour
Me.Cursor = Cursors.Default
MParent.PB1.Enabled = False
End Sub
Thanks anyway
Jeff
ASKER
Thanks Dez, I was typing as you sent the message.
I would of typed it a hell of a lot sooner (just as you posted the msg) but i was on my phone the whole time! Sorry mate!
Glad its working now anyway.
Cheers,
Dez
Glad its working now anyway.
Cheers,
Dez
one more thing...
Sub PassNewDataView(ByVal MyDataView As DataTable)
Me.BeginInvoke(New DelegateUpdateSource(Addre ssOf Me.ChangeSource), New Object() {MyDataView})
End Sub
There is no need for a seperate sub here... you can just call:
Me.BeginInvoke(New DelegateUpdateSource(Addre ssOf Me.ChangeSource), New Object() {MyDataView})
... from anywhere on the thread
Cheers,
Dez
Sub PassNewDataView(ByVal MyDataView As DataTable)
Me.BeginInvoke(New DelegateUpdateSource(Addre
End Sub
There is no need for a seperate sub here... you can just call:
Me.BeginInvoke(New DelegateUpdateSource(Addre
... from anywhere on the thread
Cheers,
Dez
ASKER
Even Better!
Thanks Dez.
Thanks Dez.
ASKER