Hi

I have an application which uses a backgroundWorker to do a simple file copy whilst the main UI is doing some other work.
The problem is that the RunWorkerCompleted event does not always fire and I can see no pattern as to when it may or may not work.

The BGW resides on the UI form and has these properties-
WorkerReportsProgress = false
WorkerSupportsCancellation = true

The form code simply calls Me.bgWorkerWMVexport.RunWorkerAsync()

Private Sub bgWorkerWMVExport_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgWorkerWMVexport.DoWork

        Try
            If Me.bgWorkerWMVexport.CancellationPending Then Return
            If My.Settings.webExport Then 'export wmv to web folder
                exportWeb(strWorkFileName + ".wmv")
            End If

            e.Result = "ok"
        Catch ex As Exception
            e.Result = ex.Message
        End Try
End Sub


    Private Sub bgWorkerWMVExport_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgWorkerWMVexport.RunWorkerCompleted
            bWmvExport = True
            If Not e.Result.ToString & "" = "" Then
                MsgBox(e.Result)
            End If
    End Sub

The code always completes the DoWork sub and never produces an exception.
The code seldom enters the RunWorkerCompleted sub but thats totally random.

Anyone have any clues what's going on?

I am not saying this is the source of your error, but it is sure a strange statement.

Not e.Result.ToString & "" = ""

Unless there a Cancelation pending before the DoWork event fired, e.Result should always be some type of string object, either "ok" or an error message. In the case of a Cancelation, e.Result would be Nothing and e.Result.ToString should err as you can not call ToString on Nothing.

If your intent was to determine if the BGW was canceled, I would suggest changing:

If Me.bgWorkerWMVexport.CancellationPending Then Return

to

If Me.bgWorkerWMVexport.CancellationPending Then 
    e.cancel=true
    Return
end if

Then in the completion handler you could test e.Cancelled instead.

No its not the problem.
I was playing with that to parse the results of the exportWeb function in the DoWork sub back to the gui via RunWorkerCompleted.
I should have cleaned that up before posting...

I did not mention it before because I could not remember why I thought it was a bad idea, but you are directly referencing the backgroundworker in the DoWork handler. I still don't know the remifications of doing so, but the documentation tells us not it's example. http://msdn.microsoft.com/en-us/library/ms233672%28v=vs.80%29.aspx

So instead of:

Private Sub bgWorkerWMVExport_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgWorkerWMVexport.DoWork
    Try
        If Me.bgWorkerWMVexport.CancellationPending Then Return

try this:

Private Sub bgWorkerWMVExport_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgWorkerWMVexport.DoWork
    Dim bgw as BackgroundWorker = Ctype(sender, backgroundworker)

    Try
        If bgw.CancellationPending Then Return

Maybe what you are experiencing is the reason for this?

Thanks for that. Didn't realise that would be a problem.

Corrected my code but unfortunately its still problematic.

Well at least now I know the reason for doing it that way.

I would appreciate it if you could close this thread out.
Thanks

Can't close the thread as I still have the original problem with RunWorkerCompleted but thanks for your help.

Sorry I misunderstood you. I thought you were having other issues.

Can you post your ExportWeb Method?

Ok, glad I haven't scared you off :)

Heres the current DoWork. Note the export line is currently commented out. It fails to trigger the RunWorkerCompleted sub regardless of whether this line is actioned or not so the problem is not there.
e.result is used to get status messages back to the gui via RunWorkerCompleted

    Private Sub bgWorkerWMVExport_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgWorkerWMVexport.DoWork
        'move wmv's to folders in background to save time
        Dim bgw As BackgroundWorker = CType(sender, backgroundworker)
        Dim iPlasma As Integer = 0
        Try
            ' If Me.bgWorkerWMVexport.CancellationPending Then Return
            If bgw.CancellationPending Then Return
            e.Result = My.Settings.plasmaExport
            If My.Settings.plasmaExport Then 'export wmv to plasma
                'iPlasma = exportPlasma(strWorkFileName + ".wmv")
            End If

            e.Result = iPlasma.ToString
        Catch ex As Exception
            e.Result = ex.Message
        End Try
    End Sub

Private Sub bgWorkerWMVExport_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgWorkerWMVexport.RunWorkerCompleted
    If Not e.Result.ToString & "" = "" Then
        If CInt(e.Result.ToString) = -1 Then
            Me.lblStatus.Text = "Website path does not exist."
            Me.lblStatus.BackColor = Color.Salmon
        Else
            My.Settings.plasmaExportCount = CInt(e.Result.ToString)
            My.Settings.Save()
            Me.lblExport.Text = e.Result.ToString
        End If
    Else
        MsgBox(e.Result.ToString)
    End If
End Sub


    Private Function exportPlasma(ByVal sFileName As String) As Integer
    'do a plasma export every x application starts
    '***THREADING***
    If My.Settings.plasmaExportCount >= My.Settings.plasmaExportPeriod Then
        If IO.Directory.Exists(My.Settings.plasmaPath) Then
            Dim sDst As String = IO.Path.GetFileNameWithoutExtension(sFileName) + ".tmp"
            Try
                IO.File.Copy(My.Settings.bufferPath + sFileName, My.Settings.plasmaPath + sDst, True)
                If IO.File.Exists(My.Settings.plasmaPath + sFileName) Then IO.File.Delete(My.Settings.plasmaPath + sFileName)
                IO.File.Move(My.Settings.plasmaPath + sDst, My.Settings.plasmaPath + sFileName)
            Catch ex As Exception
                Return -1
            End Try
            Return 0
        Else
            Return -1
        End If
    Else
        Return My.Settings.plasmaExportCount + 1
    End If
End Function

BTW this is in VB2008 with all service packs.

I don't scare easy. Get peeved at lazy fools yes.

But you do not fit that category and are making an effort yourself by eliminating the obvious.

I have not yet asked, but how have you determined that the completed event is not being called.

Did you determine it by debug messages or missing results.

By messages I mean adding:

Debug.WriteLine("leaving Dowork")
Debug.WriteLine("Entering Completed")

These show up in the Immediate Window (cntrl-Alt-I).

I've stepped through the code whilst in the DoWork and had a break point at line 1 in RunWorkerCompleted.
Have used debug.writes but in case threading affected these, I also used e.results.
When it works, the 1st line break point in RunWorkerCompleted highlights, otherwise it doesn't. Black and white results. The code in the DoWork sub always completes.

I'm running out of ideas here. The only thing that I can think of that may still be an issue is that you are accessing My.Settings.plasmaExport in DoWork. This is something that frankly I have never found a good answer to, so I tend to error on the safe side and pass anything that is created on the UI thread using the parameter object. If you need to pass more one item you can create a class or pass an Object array depending on your needs. It appears that you only need the one item so it is simple.

bgWorkerWMVExport.RunWorkerAsync(My.Settings.plasmaExport)

then in DoWork

Dim plasmaExport as String = Ctype(e.Argument, String) ' I assumed string here
.
.
.
e.Result = plasmaExport

I doubt that this is the issue, but its worth a try.

The only other thing that comes to mind, is that sometimes VS gets messed up and a restart is needed. And when all else fails try a reboot.

Good luck with this. I'm calling it night. Maybe someone else has an idea.

Thanks for your help.
I'll have a play with some static setting values and see what happens...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.