I have a search function in my program that uses a background worker in order to get the results. The Progress changed event is used to update the listview with the new item.
Private Sub SearchWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles SearchWorker.ProgressChanged
Dim itmX As ListViewItem
Dim tmpCustomer As CustomerItem
If e.UserState.ToString = "New" Then
lstResults.Items.Clear()
Else
Try
tmpCustomer = e.UserState
itmX = lstResults.Items.Add(tmpCustomer.CustomerName) ' <-- Error here
itmX.Tag = tmpCustomer.CustomerID
itmX.Name = tmpCustomer.CustomerID
itmX.SubItems.Add(tmpCustomer.City)
itmX.SubItems.Add(tmpCustomer.State)
itmX.SubItems.Add(tmpCustomer.Zip)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
progBar.Value = e.ProgressPercentage
Application.DoEvents()
End Sub
And I get this error
An unhandled exception of type 'System.StackOverflowException' occurred in System.Windows.Forms.dll
I've tried this, but it doesn't make a difference
Private Sub SearchWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles SearchWorker.ProgressChanged
If e.UserState.ToString = "New" Then
lstResults.Items.Clear()
Else
Try
itmX = lstResults.Items.Add("Test")
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
progBar.Value = e.ProgressPercentage
Application.DoEvents()
End Sub
Edit: Oh, and if I just step through the code, it doesn't have any problems.
Edit 2:
Here is the backgroundworker DoWork event:Sub doSearch(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles SearchWorker.DoWork
canceled = False
If curSearch = doSearchText Then
canceled = True
Exit Sub
End If
curSearch = doSearchText
SearchWorker.ReportProgress(0, "New")
Dim rSelect As New ADODB.Recordset
Dim CustomerID As Integer = MakeNumeric(doSearchText)
Dim sSql As String = "SELECT DISTINCT CustomerID, CustomerName, City, State, Zip FROM qrySearchFieldsQuick WHERE "
Dim sWhere As String = "CustomerID = " & CustomerID & " OR CustomerName Like '" & doSearchText & "%'"
If Not doSearchText.Contains(" ") Then
sWhere &= " OR FirstName Like '" & doSearchText & "%' OR LastName Like '" & doSearchText & "%'"
Else
Dim str() As String = doSearchText.Split(" ")
sWhere &= " OR (FirstName Like '" & str(0) & "%' AND LastName Like '" & str(1) & "%')"
End If
Dim i As Integer = 0
Dim tmpCustomer As CustomerItem
With rSelect
.Open(sSql & sWhere & " ORDER BY CustomerName", MyCn, ADODB.CursorTypeEnum.adOpenStatic, ADODB.LockTypeEnum.adLockReadOnly)
Do While Not .EOF
If SearchWorker.CancellationPending Then
canceled = True
Exit Do
End If
Do While IsDBNull(.Fields("CustomerID").Value)
.MoveNext()
Loop
tmpCustomer.CustomerID = "c" & .Fields("CustomerID").Value
tmpCustomer.CustomerName = NZ(.F开发者_如何学Goields("CustomerName").Value, "").ToString.Trim
tmpCustomer.City = Trim(NZ(.Fields("City").Value, ""))
tmpCustomer.State = Replace(Trim(NZ(.Fields("State").Value, "")), ",", "")
tmpCustomer.Zip = Trim(NZ(.Fields("Zip").Value, ""))
SearchWorker.ReportProgress((i / .RecordCount) * 100, tmpCustomer)
i += 1
Application.DoEvents()
aMoveNext:
.MoveNext()
Loop
.Close()
End With
End Sub
I think the problem is likely this line:
Application.DoEvents()
If your BackgroundWorker
is queueing up ProgressChanged
events fast enough, each call to Application.DoEvents()
will work through the message queue, come to a ProgressChanged
event, update the progress, call Application.DoEvents()
, work through the message queue, come to a ProgressChanged
event, etc.. essentually causing a recursive behavior in your code.
Try removing that call and see if the problem goes away.
Application.DoEvents()
That's the trouble maker. You added it because you noticed that the user interface still froze, even though you used a BGW. Problem is, when it pumps the events, your BGW has called ReportProgress again. Causing ProgressChanged to run again. Causing DoEvents to get called again. That works for maybe a few seconds until the ui thread runs out of stack space. Kaboom.
You'll have to delete the DoEvents() call. And solve the real problem, your BGW is calling ReportProgress way too often. Causing the ui thread to be flooded with invoke requests to call ProgressChanged. Causing it to no longer take care of its regular duties. Including painting and responding to user input.
Call ReportProgress not more often than 20 times per second. That looks smooth to the human eye. Collect calculation results so you'll have a bunch of work ready to process. If your worker produces results faster than the ui thread can display them then you have no option but to slow it down forcefully.
精彩评论