I am trying to figure out why my background worker's RunWorkerCompleted event is not always firing. Executing this same exact code, sometimes the event fires and sometimes it does not. Any help would be greatly appreciated.
I wired up a button to call RefreshStudents.
I wired up a button to call RefreshStudents.
vb.net Code:
''' <summary> ''' Refreshes the student list based on the value of the student refresh flag. ''' </summary> Private Sub RefreshStudents() Try 'if not already busy If Not brwStudents.IsBusy Then oStudentLookup.Clear() 'clear any existing rows grdStudents.PrimaryGrid.Rows.Clear() 'update the status sStatusStudentMGT = "Retrieving student records..." : UpdateStudentManagementFooter() 'set the now rows text grdStudents.PrimaryGrid.NoRowsText = "Retrieving student records..." 'set the wait cursor grdStudents.UseWaitCursor = True 'show progress pgbMain.Visible = True 'retrieve the list students brwStudents.RunWorkerAsync(Me) Else 'already busy 'cancel the current operation brwStudents.CancelAsync() End If 'if not already busy Catch ex As Exception 'handle the exception MsgBox(ex.Message) End Try End Sub Private Sub brwStudents_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles brwStudents.DoWork Try Dim fMain As frmLoad = TryCast(e.Argument, frmLoad) 'if we have a main form (UI thread) reference If (fMain IsNot Nothing) Then Dim oGrid As SuperGridControl = fMain.grdStudents Dim bResult As Boolean = True Dim oWorker As System.ComponentModel.BackgroundWorker = CType(sender, System.ComponentModel.BackgroundWorker) 'loop thru all the students For iIndex As Integer = 1 To 10000 Step 1 'exit the loop if cancellation is pending If oWorker.CancellationPending Then e.Cancel = True : Exit For 'insert the student row If Not UpdateDataRowStudent(oGrid, "ID:" & CStr(iIndex), "ID:" & CStr(iIndex), "First:" & CStr(iIndex), "Last:" & CStr(iIndex), True, True) Then bResult = False : Exit For Next iIndex 'set the result e.Result = bResult End If 'if we have a main form (UI thread) reference Catch ex As Exception 'set the result to false on error (exception will be stored in the Error property) e.Result = False End Try End Sub Private Sub brwStudents_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles brwStudents.RunWorkerCompleted Dim sErrorMessage As String = String.Empty Try 'if no errors occurred during the request If (e.Error Is Nothing) Then 'if we have a result If (e.Result IsNot Nothing) Then 'if the result was an exception If (TypeOf e.Result Is Exception) Then 'set the error message sErrorMessage = DirectCast(e.Result, Exception).Message ElseIf Not CBool(e.Result) Then 'request failed for another reason 'set the error message sErrorMessage = "List students failed." ElseIf CBool(e.Result) Then 'request was successful Dim oGridPanel As GridPanel = grdStudents.PrimaryGrid 'if we have rows If (oGridPanel.Rows.Count > 0) Then Dim oRow As GridRow = If(oGridPanel.ActiveRow Is Nothing, CType(oGridPanel.Rows(0), GridRow), CType(oGridPanel.ActiveRow, GridRow)) 'select the 1st row oGridPanel.ClearSelectedRows() : oGridPanel.SetSelected(oRow, True) : oGridPanel.SetActiveRow(oRow) End If 'if we have rows End If 'if the result was an exception Else 'unexpected result 'set the error message sErrorMessage = "List students failed." End If 'if we have a result Else 'exception occurred 'set the error message sErrorMessage = e.Error.Message End If 'if no errors occurred during the request Catch ex As Exception 'set the error message sErrorMessage = ex.Message Finally 'update the status sStatusStudentMGT = String.Empty : UpdateStudentManagementFooter() 'if no errors occurred during the request If String.IsNullOrEmpty(sErrorMessage) Then 'reset the now rows text grdStudents.PrimaryGrid.NoRowsText = "No students" Else 'errors occurred during the request 'set the now rows text to the error message grdStudents.PrimaryGrid.NoRowsText = sErrorMessage End If 'if no errors occurred during the request 'reset the wait cursor grdStudents.UseWaitCursor = False 'hide progress pgbMain.Visible = False End Try End Sub Private Function UpdateDataRowStudent(ByRef oGrid As SuperGridControl, ByVal sGUID As String, ByVal sID As String, ByVal sFirstName As String, ByVal sLastName As String, ByVal bIsActive As Boolean, ByVal bIsNewRow As Boolean) As Boolean Try Dim bResult As Boolean 'if we have a target grid If (oGrid IsNot Nothing) Then Dim oRow As GridRow Dim oPrimaryPanel As GridPanel = oGrid.PrimaryGrid 'if a new row is to be inserted into the grid If bIsNewRow Then Dim sRowData(GetType(StudentDataColumns).GetEnumNames.Count - 1) As Object 'instantiate an empty student row oRow = New GridRow(sRowData) 'insert a new row (activate the row if an invoke is not required - new student) InsertRowData(oPrimaryPanel, oRow) Else 'modify/update row 'reference the active student row oRow = CType(oPrimaryPanel.ActiveRow, GridRow) End If 'if a new row is to be inserted into the grid 'set the reference to the student's GUID in the row tag oRow.Tag = sGUID 'store the student GUID UpdateCellData(oRow.Item(StudentDataColumns.GUID), sGUID) 'store the student ID UpdateCellData(oRow.Item(StudentDataColumns.PublicID), sID) 'store the student first name UpdateCellData(oRow.Item(StudentDataColumns.FirstName), sFirstName) 'store the student last name UpdateCellData(oRow.Item(StudentDataColumns.LastName), sLastName) 'store the active flag UpdateCellData(oRow.Item(StudentDataColumns.Active), bIsActive) 'set the result bResult = True 'if a new row is to be inserted into the grid If bIsNewRow Then 'add the student to the lookup table If Not oStudentLookup.ContainsKey(sGUID) Then oStudentLookup.Add(sGUID, (sFirstName & " " & sLastName).Trim) Else 'modify/update row 'update the student to the lookup table If oStudentLookup.ContainsKey(sGUID) Then oStudentLookup(sGUID) = (sFirstName & " " & sLastName).Trim End If 'if a new row is to be inserted into the grid 'if in worker thread If Not oGrid.InvokeRequired Then 'perform any layout logic (required in order to update the selection) oGrid.ArrangeGrid() 'select the updated row oPrimaryPanel.ClearSelectedRows() : oPrimaryPanel.SetSelected(oRow, True) : oPrimaryPanel.SetActiveRow(oRow) End If 'if in worker thread End If 'if we have a target grid 'return the result Return bResult Catch ex As Exception 'throw the exception Throw End Try End Function ''' <summary> ''' Thread-safe delegate used to handle the updating of a grid cell's data. ''' </summary> ''' <param name="oCell">A reference to the target cell.</param> ''' <param name="oData">The cell data.</param> Private Sub UpdateCellData(ByVal oCell As GridCell, ByVal oData As Object) Try 'if we have a cell If (oCell IsNot Nothing) Then 'if must invoke the method If (oCell.SuperGrid IsNot Nothing) AndAlso oCell.SuperGrid.InvokeRequired Then 'invoke the method on the UI thread oCell.SuperGrid.BeginInvoke(New UpdateCellDataDelegate(AddressOf UpdateCellData), oCell, oData) Else 'invoke not required 'set the value oCell.Value = If((oData Is Nothing), String.Empty, oData) End If 'if must invoke the method End If 'if we have a cell Catch ex As Exception 'handle the exception MsgBox(ex.Message) End Try End Sub ''' <summary> ''' Delegate used to handle the updating of a grid cell's data. ''' </summary> ''' <param name="oCell">A reference to the target cell.</param> ''' <param name="eColor">The text color of the cell.</param> Private Sub UpdateCellColor(ByVal oCell As GridCell, ByVal eColor As Drawing.Color) Try 'if we have a cell, set the color If (oCell IsNot Nothing) Then oCell.CellStyles.ReadOnly.TextColor = eColor : oCell.CellStyles.Default.TextColor = eColor Catch ex As Exception 'handle the exception Throw End Try End Sub ''' <summary> ''' Thread-safe delegate used to handle the insertion of rows into a grid panel. ''' </summary> ''' <param name="oGridPanel">A reference to the target grid panel.</param> ''' <param name="oData">A reference to the data row.</param> Private Sub InsertRowData(ByVal oGridPanel As GridPanel, ByVal oData As GridRow) Try 'if we have a grid panel and data If (oGridPanel IsNot Nothing) AndAlso (oData IsNot Nothing) Then 'if an invoke is required If oGridPanel.SuperGrid.InvokeRequired Then 'invoke the method on the UI thread oGridPanel.SuperGrid.BeginInvoke(New InsertRowDataDelegate(AddressOf InsertRowData), oGridPanel, oData) Else 'on UI thread 'add the data to the collection oGridPanel.Rows.Add(oData) End If 'if an invoke is required End If 'if we have a grid panel and data Catch ex As Exception 'handle the exception Throw End Try End Sub