-
Dec 14th, 2008, 03:13 PM
#1
Thread Starter
Lively Member
[SOLVED] BGW Problems? cross thread calls
Hi been a while since I played !
Right here goes I was playing and moved tome code to use a background worker. I dropped a backgroundworker on my form Set workerreportsprogress to true and the workersupportscancellation to true.....
The first time i call the BGW all is ok but any other calls to the BGW i get
InvalidOperationException with the message, "Control control name accessed from a thread other than the thread it was created on." in the
ShowDrivesWorker_ProgressChanged sub
vb Code:
Private Sub ShowDrivesWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles ShowDrivesWorker.ProgressChanged
Me.ToolStripProgressBar1.Value = e.ProgressPercentage
Me.ToolStripStatusLabel1.Text = "Finding Removable Drives"
Me.ComboBox1.Items.Add(e.UserState)
nocard = False
Me.Button1.Enabled = True
End Sub
Private Sub ShowDrivesWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles ShowDrivesWorker.RunWorkerCompleted
Me.ToolStripProgressBar1.Value = 0
Me.ToolStripStatusLabel1.Text = "Ready"
Me.ShowDrivesWorker.CancelAsync()
End Sub
Why would I not be able to access controls on the form from ShowDrivesWorker_ProgressChanged sub?
Any help would be great first time use of BGW
Last edited by polecat; Dec 21st, 2008 at 09:04 AM.
Reason: Solved
-
Dec 14th, 2008, 05:09 PM
#2
Hyperactive Member
Re: [2005] BGW Problems? cross thread calls
can you show us how you're invoking the background worker?
-
Dec 14th, 2008, 05:46 PM
#3
Re: [2005] BGW Problems? cross thread calls
First up, why are you calling CancelAsync in the RunWorkerCompleted event handler? The work has already completed by that stage so what are you cancelling?
Secondly, we really need to see your DoWork event handler to be able to answer this question.
-
Dec 15th, 2008, 12:44 AM
#4
Thread Starter
Lively Member
Re: [2005] BGW Problems? cross thread calls
I just put the CancelAsync in the RunWorkerCompleted event as a test
im calling the BGW in my form load event
Code:
'Call BGW
ShowDrivesWorker.RunWorkerAsync()
My DoWork runs a loop and calls ShowDrivesWorker.ReportProgress
does not touch any controls
Code:
Private Sub ShowDrivesWorker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles ShowDrivesWorker.DoWork
Const Removable As Integer = 2
Dim Scope As ManagementScope = New ManagementScope(ManagementPath.DefaultPath)
Dim Query As New SelectQuery("Win32_LogicalDisk")
Dim Searcher As New ManagementObjectSearcher(Scope, Query)
Dim Iterator As ManagementObject
Dim si As Integer = 0
For Each Iterator In Searcher.Get()
If Iterator.Item("DriveType").ToString = Removable.ToString Then
si = si + 10
Dim item As String = Iterator.Item("DeviceID").ToString & "\"
ShowDrivesWorker.ReportProgress(si, item)
nocard = False
End If
Next
If nocard = True Then
MessageBox.Show("Please insert your card reader!" & vbCrLf & "No USB Reader Found", "No SD Card found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If
End Sub
First time it works in the form load but if I call ShowDrivesWorker.RunWorkerAsync() again I get the errors in the update sub..
Many thanks for looking
-
Dec 15th, 2008, 01:00 AM
#5
Re: [2005] BGW Problems? cross thread calls
When you call RunWorkerAsync the second time you aren't calling it from a background thread are you? The ProgressChanged event is marshaled to the thread on which RunWorkerAsync was called so if that wasn't the UI thread then you can't access controls in the ProgressChanged event handler. RunWorkerAsync should ONLY be called from a thread that owns the controls you want to access, which basically means only the UI thread.
Also, you should not be calling MessageBox.Show in the DoWork event handler. A message box is supposed to be a modal dialogue but if you display it on a background thread it will NOT prevent you accessing the calling for. As such the user could conceivably ignore that message and your background thread would never complete. You should be displaying that message from the RunWorkerCompleted event handler. You can use the e.Result property to pass a value that indicates the result. Follow the BackgroundWorker link in my signature for an example.
-
Dec 15th, 2008, 02:02 PM
#6
Thread Starter
Lively Member
Re: [2005] BGW Problems? cross thread calls
Again the msgbox's were just for me to see what was going on without using breakpoints and will be removed.
ERM you know what jmcilhinney your right on yes it is another bg thread calling the RunWorkerAsync .... Damn how do i get around that?
Create a new public sub that calls the RunWorkerAsync then call the new sub from bg thread ?
-
Dec 15th, 2008, 05:16 PM
#7
Re: [2005] BGW Problems? cross thread calls
Assuming you do need to start the background thread from a background thread, you have two choices that I can see:
1. Invoke a method on the UI thread to start the BackgroundWorker. That's pretty simple if you follow the instructions in my Controls & Multithreading link.
2. Don't use a BackgroundWorker at all and always use delegation to access the UI.
-
Dec 15th, 2008, 05:30 PM
#8
Re: [2005] BGW Problems? cross thread calls
you can use delegation AND a backgroundworker component cant you? I mean, isnt a backgroundworker just a System.Threading.Thread with a few handy properties/methods stuck onto it?
But then having said that, thats essentially what the ReportProgress method does isnt it... it works just like a delegate sub would do. So why couldn't you just have your ReportProgress method call the RunWorkerASync method of the second bgworker in the WorkerReportsProgress event of your first bgworker?
-
Dec 15th, 2008, 06:29 PM
#9
Re: [2005] BGW Problems? cross thread calls
Originally Posted by chris128
you can use delegation AND a backgroundworker component cant you? I mean, isnt a backgroundworker just a System.Threading.Thread with a few handy properties/methods stuck onto it?
But then having said that, thats essentially what the ReportProgress method does isnt it... it works just like a delegate sub would do. So why couldn't you just have your ReportProgress method call the RunWorkerASync method of the second bgworker in the WorkerReportsProgress event of your first bgworker?
You certainly can use a BackgroundWorker and delegation. The whole point of the BackgroundWorker is that you don't have to though, so if you don't use the ProgressChanged and/or RunWorkerCompleted events then using a BackgroundWorker is pretty pointless. You might use those events AND some explicit delegation though.
I will pull you up on one point though because it's a misconception that a lot of people have. a BackgroundWorker is NOT a Thread and it's nothing like a Thread. The BackgroundWorker is a component that hides some of the complexity of multi-threading by handling it internally for you. You call RunWorkerAsync and it will raise its DoWork event on a thread pool thread. Your DoWork event handler then gets executed on that thread, just like if you'd called ThreadPool.QueueUserWorkItem. You call ReportProgress and the BackgroundWorker handles the delegation internally and raises its ProgressChanged event on whatever thread it was started on. Your ProgressChanged event handler is then executed on the same thread you called RunWorkerAsync on. The same goes for the RunWorkerCompleted event. It gets raised when the work is done and, again, the BGW handles the delegation internally.
-
Dec 15th, 2008, 06:42 PM
#10
Re: [2005] BGW Problems? cross thread calls
Ah I see, thanks for the info (as always)
-
Dec 21st, 2008, 09:02 AM
#11
Thread Starter
Lively Member
Re: [2005] BGW Problems? cross thread calls
Sorted now guys thanks for the input had to use delegates in the end all is well
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|