-
Jun 7th, 2016, 02:52 PM
#1
Thread Starter
Hyperactive Member
[RESOLVED] Background Worker Issues
For some strange reason I can not get the background worker to fire. Here is my code.
I create the worker then I do some UI work to gather information.
Then upon Button Click I fire off the UpdateStatus routine. That will process a CSV File that can be anywhere from 100 records to 500K+. Doing the work in the button click takes anywhere from a few seconds to 10 minutes.
I would like to move it to a BW and free up the UI and just have a progress bar going. For some reason I'm having difficulties with it. When I step through the program it executes the RunAsyc but never steps through the BW.
I click RUN and my breakpoint in the BW never fires. I also never get a refresh of the progress bar.
Does anyone see an issue with my code?
Thanks,
-NJ
Code:
Private WithEvents mWorker As _
New BackgroundWorker()
Code:
mWorker.WorkerSupportsCancellation = True
mWorker.WorkerReportsProgress = True
mWorker.RunWorkerAsync()
Code:
Private Sub UpdateStatus(ByVal progress As Integer, ByVal status As String)
Try
If Me.InvokeRequired Then
Dim cb As New UpdateStatusCallback(AddressOf UpdateStatusDelegate)
Me.Invoke(cb, New Object() {progress, status})
Else
UpdateStatusDelegate(progress, status)
End If
Catch ex As Exception
MessageBox.Show("There was an error " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Code:
Private Delegate Sub UpdateStatusCallback(ByVal progress As Integer, ByVal status As String)
Code:
Private Sub UpdateStatusDelegate(ByVal progress As Integer, ByVal status As String)
Loading.LoadingProgressBar.Value = progress
Loading.StartLbl.Text = "Adding " + Loading.LoadingProgressBar.Value.ToString()
'Label1.Text = status
Loading.LoadingProgressBar.Refresh()
Loading.StartLbl.Refresh()
End Sub
Code:
Private Sub mWorker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles mWorker.RunWorkerCompleted
Loading.Close()
Loading.Dispose()
End Sub
This is the code that never fires
Code:
Private Sub mWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles mWorker.DoWork
Dim MySQLCEConnection As SqlCeConnection = New SqlCeConnection
Dim MySQLCECommand As SqlCeCommand = New SqlCeCommand
Dim Callinsert3 As New UpdateCountryCodes
Dim MyPath As String = Application.StartupPath
Dim StartIP As String = " "
Dim EndIP As String = " "
Dim CountryName As String = " "
Dim CountryRegion As String = " "
Dim CountryCity As String = " "
Dim CountryCode As String = " "
Dim CurrentRow()
Dim line As String = Nothing
Dim ReturnedValue As String = Nothing
Dim FileToProcess As String = MyPath + "\WorkFile.csv"
Dim myReader As New TextFieldParser(FileToProcess)
Dim lineCount As Integer = File.ReadAllLines(FileToProcess).Length
Dim RecordCount As Int32 = 0
Dim DoEventsCounter As Int32 = 5000
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCEConnection.Close()
MySQLCEConnection.Dispose()
GC.Collect()
End If
Dim Myconstring As String = "XXXXXXXX"
mySQLCom = "Insert Into GEOLocation(GEO_Start_IP, GEO_End_IP, GEO_Country_Code, GEO_Country_Name, GEO_Country_Region, GEO_Country_City)" +
" Values (@StartIP, @EndIP, @CountryCode, @CountryName, @CountryRegion, @CountryCity)"
Try
MySQLCEConnection = New SqlCeConnection(Myconstring)
If MySQLCEConnection.State = Data.ConnectionState.Closed Then
MySQLCEConnection.Open()
End If
MySQLCECommand = New SqlCeCommand(mySQLCom, MySQLCEConnection)
Catch ex As Exception
End Try
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@StartIP"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@EndIP"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryCode"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryName"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryRegion"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryCity"
While Not MyReader.EndOfData
Try
CurrentRow = MyReader.ReadFields
StartIP = CurrentRow(0)
EndIP = CurrentRow(1)
CountryCode = CurrentRow(2)
CountryName = CurrentRow(3)
CountryRegion = CurrentRow(4)
CountryCity = CurrentRow(5)
Try
MySQLCECommand.Parameters.Item("@StartIP").Value = StartIP
MySQLCECommand.Parameters.Item("@EndIP").Value = EndIP
MySQLCECommand.Parameters.Item("@CountryCode").Value = CountryCode
MySQLCECommand.Parameters.Item("@CountryName").Value = CountryName
MySQLCECommand.Parameters.Item("@CountryRegion").Value = CountryRegion
MySQLCECommand.Parameters.Item("@CountryCity").Value = CountryCity
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCECommand.ExecuteNonQuery()
RecordCount = RecordCount + 1
UpdateStatus(RecordCount, "Running")
End If
Catch ex As SqlCeException
UpdateStatus(RecordCount, "SQL Error")
End Try
Catch ex As Exception
UpdateStatus(RecordCount, "Read Error")
End Try
End While
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCEConnection.Close()
MySQLCEConnection.Dispose()
GC.Collect()
End If
End Sub
Lo And Behold
This is my first Microsoft App Submission
Your opinion of it would be appreciated
-
Jun 7th, 2016, 03:11 PM
#2
Re: Background Worker Issues
Well, hm. The most logical explanation for the breakpoint not being hit would be "the event isn't wired up correctly". I don't like using WithEvents when I declare a thing myself, I prefer using AddHandler to set up the event handlers.
If it were running and an exception were unhandled, you'd still get the RunWorkerCompleted event and the exception would be in e.Error. I'm assuming you have a breakpoint there or at least don't observe the side effects.
UpdateStatus() seems fine, albeit archaic. It could be cleaned up using some more modern syntax, and you could be using the worker's ReportProgress() method, but it's doing the right thing.
So let's try this. Take the WithEvents and Handles out of everything. Update your code to look like this:
Code:
AddHandler mWorker.DoWork, AddressOf mWorker_DoWork
AddHandler mWorker.RunWorkerCompleted, AddressOf mWorker_RunWorkerCompleted
mWorker.WorkerSupportsCancellation = True
mWorker.WorkerReportsProgress = True
mWorker.RunWorkerAsync()
Does that make things work? If so, something you did disturbed the mystical fabric that makes WithEvents work, and it's probably easier to use AddHandler than figure out exactly what went wrong.
There's a couple of other things I don't like, but this is the most suspicious thing that might make it not work.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Jun 7th, 2016, 03:24 PM
#3
Re: Background Worker Issues
Originally Posted by NJDevils28
For some strange reason I can not get the background worker to fire. Here is my code.
I create the worker then I do some UI work to gather information.
Then upon Button Click I fire off the UpdateStatus routine. That will process a CSV File that can be anywhere from 100 records to 500K+. Doing the work in the button click takes anywhere from a few seconds to 10 minutes.
I would like to move it to a BW and free up the UI and just have a progress bar going. For some reason I'm having difficulties with it. When I step through the program it executes the RunAsyc but never steps through the BW.
I click RUN and my breakpoint in the BW never fires. I also never get a refresh of the progress bar.
Does anyone see an issue with my code?
Thanks,
-NJ
Code:
Private WithEvents mWorker As _
New BackgroundWorker()
Code:
mWorker.WorkerSupportsCancellation = True
mWorker.WorkerReportsProgress = True
mWorker.RunWorkerAsync()
Code:
Private Sub UpdateStatus(ByVal progress As Integer, ByVal status As String)
Try
If Me.InvokeRequired Then
Dim cb As New UpdateStatusCallback(AddressOf UpdateStatusDelegate)
Me.Invoke(cb, New Object() {progress, status})
Else
UpdateStatusDelegate(progress, status)
End If
Catch ex As Exception
MessageBox.Show("There was an error " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Code:
Private Delegate Sub UpdateStatusCallback(ByVal progress As Integer, ByVal status As String)
Code:
Private Sub UpdateStatusDelegate(ByVal progress As Integer, ByVal status As String)
Loading.LoadingProgressBar.Value = progress
Loading.StartLbl.Text = "Adding " + Loading.LoadingProgressBar.Value.ToString()
'Label1.Text = status
Loading.LoadingProgressBar.Refresh()
Loading.StartLbl.Refresh()
End Sub
Code:
Private Sub mWorker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles mWorker.RunWorkerCompleted
Loading.Close()
Loading.Dispose()
End Sub
This is the code that never fires
Code:
Private Sub mWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles mWorker.DoWork
Dim MySQLCEConnection As SqlCeConnection = New SqlCeConnection
Dim MySQLCECommand As SqlCeCommand = New SqlCeCommand
Dim Callinsert3 As New UpdateCountryCodes
Dim MyPath As String = Application.StartupPath
Dim StartIP As String = " "
Dim EndIP As String = " "
Dim CountryName As String = " "
Dim CountryRegion As String = " "
Dim CountryCity As String = " "
Dim CountryCode As String = " "
Dim CurrentRow()
Dim line As String = Nothing
Dim ReturnedValue As String = Nothing
Dim FileToProcess As String = MyPath + "\WorkFile.csv"
Dim myReader As New TextFieldParser(FileToProcess)
Dim lineCount As Integer = File.ReadAllLines(FileToProcess).Length
Dim RecordCount As Int32 = 0
Dim DoEventsCounter As Int32 = 5000
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCEConnection.Close()
MySQLCEConnection.Dispose()
GC.Collect()
End If
Dim Myconstring As String = "XXXXXXXX"
mySQLCom = "Insert Into GEOLocation(GEO_Start_IP, GEO_End_IP, GEO_Country_Code, GEO_Country_Name, GEO_Country_Region, GEO_Country_City)" +
" Values (@StartIP, @EndIP, @CountryCode, @CountryName, @CountryRegion, @CountryCity)"
Try
MySQLCEConnection = New SqlCeConnection(Myconstring)
If MySQLCEConnection.State = Data.ConnectionState.Closed Then
MySQLCEConnection.Open()
End If
MySQLCECommand = New SqlCeCommand(mySQLCom, MySQLCEConnection)
Catch ex As Exception
End Try
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@StartIP"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@EndIP"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryCode"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryName"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryRegion"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryCity"
While Not MyReader.EndOfData
Try
CurrentRow = MyReader.ReadFields
StartIP = CurrentRow(0)
EndIP = CurrentRow(1)
CountryCode = CurrentRow(2)
CountryName = CurrentRow(3)
CountryRegion = CurrentRow(4)
CountryCity = CurrentRow(5)
Try
MySQLCECommand.Parameters.Item("@StartIP").Value = StartIP
MySQLCECommand.Parameters.Item("@EndIP").Value = EndIP
MySQLCECommand.Parameters.Item("@CountryCode").Value = CountryCode
MySQLCECommand.Parameters.Item("@CountryName").Value = CountryName
MySQLCECommand.Parameters.Item("@CountryRegion").Value = CountryRegion
MySQLCECommand.Parameters.Item("@CountryCity").Value = CountryCity
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCECommand.ExecuteNonQuery()
RecordCount = RecordCount + 1
UpdateStatus(RecordCount, "Running")
End If
Catch ex As SqlCeException
UpdateStatus(RecordCount, "SQL Error")
End Try
Catch ex As Exception
UpdateStatus(RecordCount, "Read Error")
End Try
End While
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCEConnection.Close()
MySQLCEConnection.Dispose()
GC.Collect()
End If
End Sub
You show lines of code that runs the worker but it lacks the context, ie, where is the code that runs the worker? Does that sub ever run either?
Too many bread crumbs with your post, nothing solid to be able to tell why your worker might not be running.
-
Jun 8th, 2016, 07:39 AM
#4
Thread Starter
Hyperactive Member
Re: Background Worker Issues
Originally Posted by Sitten Spynne
Well, hm. The most logical explanation for the breakpoint not being hit would be "the event isn't wired up correctly". I don't like using WithEvents when I declare a thing myself, I prefer using AddHandler to set up the event handlers.
If it were running and an exception were unhandled, you'd still get the RunWorkerCompleted event and the exception would be in e.Error. I'm assuming you have a breakpoint there or at least don't observe the side effects.
UpdateStatus() seems fine, albeit archaic. It could be cleaned up using some more modern syntax, and you could be using the worker's ReportProgress() method, but it's doing the right thing.
So let's try this. Take the WithEvents and Handles out of everything. Update your code to look like this:
Code:
AddHandler mWorker.DoWork, AddressOf mWorker_DoWork
AddHandler mWorker.RunWorkerCompleted, AddressOf mWorker_RunWorkerCompleted
mWorker.WorkerSupportsCancellation = True
mWorker.WorkerReportsProgress = True
mWorker.RunWorkerAsync()
Does that make things work? If so, something you did disturbed the mystical fabric that makes WithEvents work, and it's probably easier to use AddHandler than figure out exactly what went wrong.
There's a couple of other things I don't like, but this is the most suspicious thing that might make it not work.
Hi,
That did not work, so I decided to just drop a new backgroundworker on the form and start fresh. Still no joy. This is bugging the crap out of me!!!
Here is the re-worked code.
Button Click starts the Background worker. I have a break point at the first "IF" statement in the DoWork that never fires.
I have two other background workers that are running fine. The first background worker is canceled and I make sure it canceled clean before I execute the new code because that touches the same database as the new code. Background worker 2 does other work not related to the database.
I'm obviously doing something wrong, I just can't figure it out.
Code:
'Cancel BW1 and set a flag
BackgroundWorker1.CancelAsync()
BackgroundWorker1.Dispose()
BW1Cancel = True
While BackgroundWorker1.IsBusy()
Application.DoEvents()
End While
'Only start the next worker once the first ends
BackgroundWorker3.WorkerSupportsCancellation = True
BackgroundWorker3.WorkerReportsProgress = True
BackgroundWorker3.RunWorkerAsync()
Code:
Private Sub BackgroundWorker3_DoWork(sender As Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorker3.DoWork
Dim MySQLCEConnection As SqlCeConnection = New SqlCeConnection
Dim MySQLCECommand As SqlCeCommand = New SqlCeCommand
Dim Callinsert3 As New UpdateCountryCodes
Dim MyPath As String = Application.StartupPath
Dim StartIP As String = " "
Dim EndIP As String = " "
Dim CountryName As String = " "
Dim CountryRegion As String = " "
Dim CountryCity As String = " "
Dim CountryCode As String = " "
Dim CurrentRow()
Dim line As String = Nothing
Dim ReturnedValue As String = Nothing
Dim FileToProcess As String = MyPath + "\File to process.csv"
Dim myReader As New TextFieldParser(FileToProcess)
Dim lineCount As Integer = File.ReadAllLines(FileToProcess).Length
Dim RecordCount As Int32 = 0
Dim CheckforCancel As Int32 = 1000
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCEConnection.Close()
MySQLCEConnection.Dispose()
GC.Collect()
End If
Dim Myconstring As String = "Data Source=" + Trim(AppDataPath) + "\XXXXXX"
mySQLCom = "Insert Into GEOLocation(GEO_Start_IP, GEO_End_IP, GEO_Country_Code, GEO_Country_Name, GEO_Country_Region, GEO_Country_City)" +
" Values (@StartIP, @EndIP, @CountryCode, @CountryName, @CountryRegion, @CountryCity)"
Try
MySQLCEConnection = New SqlCeConnection(Myconstring)
If MySQLCEConnection.State = Data.ConnectionState.Closed Then
MySQLCEConnection.Open()
End If
MySQLCECommand = New SqlCeCommand(mySQLCom, MySQLCEConnection)
Catch ex As Exception
End Try
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@StartIP"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@EndIP"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryCode"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryName"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryRegion"
MySQLCECommand.Parameters.Add(MySQLCECommand.CreateParameter).ParameterName = "@CountryCity"
While Not myReader.EndOfData
Try
CurrentRow = myReader.ReadFields
StartIP = CurrentRow(0)
EndIP = CurrentRow(1)
CountryCode = CurrentRow(2)
CountryName = CurrentRow(3)
CountryRegion = CurrentRow(4)
CountryCity = CurrentRow(5)
Try
MySQLCECommand.Parameters.Item("@StartIP").Value = StartIP
MySQLCECommand.Parameters.Item("@EndIP").Value = EndIP
MySQLCECommand.Parameters.Item("@CountryCode").Value = CountryCode
MySQLCECommand.Parameters.Item("@CountryName").Value = CountryName
MySQLCECommand.Parameters.Item("@CountryRegion").Value = CountryRegion
MySQLCECommand.Parameters.Item("@CountryCity").Value = CountryCity
'Write a record and update the progress bar
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCECommand.ExecuteNonQuery()
RecordCount = RecordCount + 1
BackgroundWorker3.ReportProgress(RecordCount, "Running")
End If
' Check for cancel every 1000 records
If RecordCount > CheckforCancel Then
CheckforCancel = CheckforCancel + 1000
If BackgroundWorker3.CancellationPending Then
e.Cancel = True
Exit While
End If
End If
Catch ex As SqlCeException
End Try
Catch ex As Exception
End Try
End While
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCEConnection.Close()
MySQLCEConnection.Dispose()
GC.Collect()
End If
End Sub
Code:
Private Sub BackgroundWorker3_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker3.RunWorkerCompleted
Loading.Close()
Loading.Dispose()
End Sub
Code:
Private Sub BackgroundWorker3_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker3.ProgressChanged
Loading.LoadingProgressBar.Value = e.ProgressPercentage
Loading.StartLbl.Text = "Adding " + Loading.LoadingProgressBar.Value.ToString()
Loading.LoadingProgressBar.Refresh()
Loading.StartLbl.Refresh()
End Sub
Lo And Behold
This is my first Microsoft App Submission
Your opinion of it would be appreciated
-
Jun 8th, 2016, 08:01 AM
#5
Re: Background Worker Issues
In the following code, have you placed a break point on the highlighted line, and is it ever hit?
Code:
'Cancel BW1 and set a flag
BackgroundWorker1.CancelAsync()
BackgroundWorker1.Dispose()
BW1Cancel = True
While BackgroundWorker1.IsBusy()
Application.DoEvents()
End While
'Only start the next worker once the first ends
BackgroundWorker3.WorkerSupportsCancellation = True
BackgroundWorker3.WorkerReportsProgress = True
BackgroundWorker3.RunWorkerAsync()
-
Jun 8th, 2016, 08:55 AM
#6
Re: Background Worker Issues
Are you sure the BackgroundWorker is the culprit? It could be possible that the BackgroundWorker is working, but there is some problem with your code.
Seeing empty Catch blocks gives me hiccups and points towards smelly code. It is akin to ignoring the errors. At the very least I would output the error to my status box or an error log file to be sure nothing unexpected is happening.
What happens when you put a breakpoint on your BackgroundWorker3_DoWork sub and run the code. Is that breakpoint hit? Once it breaks there, go line by line and see what is going wrong.
-
Jun 8th, 2016, 09:18 AM
#7
Thread Starter
Hyperactive Member
Re: Background Worker Issues
Originally Posted by Inferrd
In the following code, have you placed a break point on the highlighted line, and is it ever hit?
Code:
'Cancel BW1 and set a flag
BackgroundWorker1.CancelAsync()
BackgroundWorker1.Dispose()
BW1Cancel = True
While BackgroundWorker1.IsBusy()
Application.DoEvents()
End While
'Only start the next worker once the first ends
BackgroundWorker3.WorkerSupportsCancellation = True
BackgroundWorker3.WorkerReportsProgress = True
BackgroundWorker3.RunWorkerAsync()
Hi,
Yes I have.
And immediately upon F11 (Step) it just goes right to the exit sub of the button click. It's as if the RunworkerAsync is not there.
When I click the <Run> the program just continues with the Loading Form painted on the screen but no interaction is detected. No refresh of any progress or firing of a break point in the DoWork.
Lo And Behold
This is my first Microsoft App Submission
Your opinion of it would be appreciated
-
Jun 8th, 2016, 09:25 AM
#8
Thread Starter
Hyperactive Member
Re: Background Worker Issues
Hi All,
Ok.
The BW2 finally fired. For some reason there was a 2 minute delay from RunAsync() to actually stepping into the code. It is a long time but I decided to just wait it out and see what happened.
The issue I was trying to reconcile is still present though. The BW2 is doing it's job of updating the database AND updating the form but when I click anywhere on the form, the form freezes and no longer updated BUT the BW is still cooking.
When the BW ends it closes the notification form and the program unfreezes.
Why would this happen? I thought the BW would alleviate this issue but it has not.
Is there code that would prevent the form from freezing?
-NJ
Lo And Behold
This is my first Microsoft App Submission
Your opinion of it would be appreciated
-
Jun 8th, 2016, 09:32 AM
#9
Lively Member
Re: Background Worker Issues
If I can offer some advice with a possible easier way to resolve your issue, make a new blank project and try to implement just the basic functionality of what you are trying to do with the BGW. This may provide a more specific idea of what is causing the issue. It will also be something that you can post the entire code here, which could then be easier to paste in a project to see what it is doing.
I know it sounds stupid, but this is often how I am able to work through these tedious errors that don't make any sense.
-
Jun 8th, 2016, 09:43 AM
#10
Thread Starter
Hyperactive Member
Re: Background Worker Issues
Originally Posted by Recoil1980
If I can offer some advice with a possible easier way to resolve your issue, make a new blank project and try to implement just the basic functionality of what you are trying to do with the BGW. This may provide a more specific idea of what is causing the issue. It will also be something that you can post the entire code here, which could then be easier to paste in a project to see what it is doing.
I know it sounds stupid, but this is often how I am able to work through these tedious errors that don't make any sense.
It might come down to that. I think it may have to do with my other BW's. When I issue the cancel for them and then I wait for them to end there seems to be either an immediate response or a long drawn out wait before my 2nd BW fires.
I'm still foggy on why my form freezes.
-NJ
Lo And Behold
This is my first Microsoft App Submission
Your opinion of it would be appreciated
-
Jun 8th, 2016, 09:51 AM
#11
Re: Background Worker Issues
I'm still not quite sure what is going on, but this is VERY suspicious:
Code:
BackgroundWorker1.CancelAsync()
BackgroundWorker1.Dispose()
BW1Cancel = True
While BackgroundWorker1.IsBusy()
Application.DoEvents()
End While
When you call Dispose() on an object, it's done. That tells .NET you are throwing it in the trash can, and will never try to use it again. Internally, it cleans up anything it was holding on to and generally puts itself in a state that won't work.
It's possible that, after disposing the BackgroundWorker, it configures itself to not raise events anymore. I'm surprised checking IsBusy doesn't throw an ObjectDisposedException. Either way, this is a shaky and unreliable way to 'connect' two BackgroundWorkers. In general, any solution with Application.DoEvents() is wrong.
So to be clear, I think what happens is you call CancelAsync(), which sets the flag indicating the worker should be cancelled, but I can't actually tell if you properly handle that in BackgroundWorker1 because I can't see that code. Either way, you immediately call Dispose(), which could potentially just terminate the worker thread without running through the normal chain of events.
The bonkers part I cannot explain is I would not expect calling IsBusy to succeed at that point.
So this is a suggestion, but I'm not confident it's the actual problem. Just a thing that will go over smoother:
It would be better to just call CancelAsync(). Then, in BackgroundWorker1's RunWorkerCompleted, you can detect the worker was canceled via the e.Cancel property. You can respond to the worker being canceled by starting worker 3. I bet that might be more successful. It'd look something like this:
Code:
'Wherever your first snippet came from:
BackgroundWorker1.CancelAsync()
BW1Cancel = True
End Sub
Sub BackgroundWorker1_RunWorkerCompleted(...) Handles ...
If e.Cancelled Then
BackgroundWorker3.WorkerSupportsCancellation = True
BackgroundWorker3.WorkerReportsProgress = True
BackgroundWorker3.RunWorkerAsync()
Else
' Whatever happens when it finishes normally
End If
End Sub
In terms of the actual problem, I think we're going to need more than just the few windows into your code you've given us. There's lots of questions. Like, where is the code in your first snippet? If it's in a Load event handler, those are notorious for swallowing exceptions and that'd hide many problems. As pradeep pointed out in #6, there's several other little problems scattered throughout the code that might be issues. I have a feeling it's just going to be a mystery until we see a lot more code.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Jun 8th, 2016, 09:52 AM
#12
Lively Member
Re: Background Worker Issues
Originally Posted by NJDevils28
It might come down to that. I think it may have to do with my other BW's. When I issue the cancel for them and then I wait for them to end there seems to be either an immediate response or a long drawn out wait before my 2nd BW fires.
I'm still foggy on why my form freezes.
-NJ
Are you trying to access UI controls through the threads? Check the fourth post on this thread. It provides a better explanation on accessing UI threads than I possibly could
-
Jun 8th, 2016, 10:22 AM
#13
Re: Background Worker Issues
Originally Posted by Sitten Spynne
I'm still not quite sure what is going on, but this is VERY suspicious:
Code:
BackgroundWorker1.CancelAsync()
BackgroundWorker1.Dispose()
BW1Cancel = True
While BackgroundWorker1.IsBusy()
Application.DoEvents()
End While
Yeah, I didn't like the look of that either which is why I asked if the lines following that were ever hit.
Originally Posted by NJDevils28
I'm still foggy on why my form freezes.
Looking at the code in your BackGroundWorker3 is executing, it seems you are:
reading a record from your database,
writing a record back to it,
reporting progress to your form
and doing that in a tight loop.
I don't know how long it takes to read and write to a database, but I imagine it would be quite quick. If the time it takes to read and write is close to or faster than the time it takes to update the form in the BackgroundWorker3_ProgressChanged Sub, then your form UI will become sluggish or freeze.
That's because the BackgroundWorker code doesn't wait while the ProgressChanged event code is executed on the UI. If the BackgroundWorker raises the ProgressChanged event faster than it can be handled, the events queue up and the UI never has a chance to respond to other events, so seems to freeze.
I'd try moving the code that raises the ProgressChanged event :
Code:
'Write a record and update the progress bar
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCECommand.ExecuteNonQuery()
RecordCount = RecordCount + 1
BackgroundWorker3.ReportProgress(RecordCount, "Running")
End If
into the code block that only checks every 1000 iterations or so:
Code:
' Check for cancel every 1000 records
If RecordCount > CheckforCancel Then
CheckforCancel = CheckforCancel + 1000
If BackgroundWorker3.CancellationPending Then
e.Cancel = True
Exit While
End If
End If
or similar.
Last edited by Inferrd; Jun 8th, 2016 at 10:25 AM.
Reason: typo
-
Jun 8th, 2016, 11:01 AM
#14
Thread Starter
Hyperactive Member
Re: Background Worker Issues
Originally Posted by Inferrd
Yeah, I didn't like the look of that either which is why I asked if the lines following that were ever hit.
Looking at the code in your BackGroundWorker3 is executing, it seems you are:
reading a record from your database,
writing a record back to it,
reporting progress to your form
and doing that in a tight loop.
I don't know how long it takes to read and write to a database, but I imagine it would be quite quick. If the time it takes to read and write is close to or faster than the time it takes to update the form in the BackgroundWorker3_ProgressChanged Sub, then your form UI will become sluggish or freeze.
That's because the BackgroundWorker code doesn't wait while the ProgressChanged event code is executed on the UI. If the BackgroundWorker raises the ProgressChanged event faster than it can be handled, the events queue up and the UI never has a chance to respond to other events, so seems to freeze.
I'd try moving the code that raises the ProgressChanged event :
Code:
'Write a record and update the progress bar
If MySQLCEConnection.State = Data.ConnectionState.Open Then
MySQLCECommand.ExecuteNonQuery()
RecordCount = RecordCount + 1
BackgroundWorker3.ReportProgress(RecordCount, "Running")
End If
into the code block that only checks every 1000 iterations or so:
Code:
' Check for cancel every 1000 records
If RecordCount > CheckforCancel Then
CheckforCancel = CheckforCancel + 1000
If BackgroundWorker3.CancellationPending Then
e.Cancel = True
Exit While
End If
End If
or similar.
Holy crap! That did it! I moved the report progress to the check cancel block and everything is working smoothly now.
I also removed the BW.Dispose() like advised.
Thank you!!!
Lo And Behold
This is my first Microsoft App Submission
Your opinion of it would be appreciated
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
|