And*_*273 1 vb.net backgroundworker
我的程序中有一个搜索功能,它使用后台工作程序来获得结果.Progress changed事件用于使用新项更新列表视图.
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
Run Code Online (Sandbox Code Playgroud)
我得到了这个错误
An unhandled exception of type 'System.StackOverflowException' occurred in System.Windows.Forms.dll
Run Code Online (Sandbox Code Playgroud)
我试过这个,但它并没有什么不同
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
Run Code Online (Sandbox Code Playgroud)
编辑:哦,如果我只是单步执行代码,它没有任何问题.
编辑2:
这是后台工作者DoWork事件:
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(.Fields("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
Run Code Online (Sandbox Code Playgroud)
我认为这个问题很可能是这样的:
Application.DoEvents()
Run Code Online (Sandbox Code Playgroud)
如果你BackgroundWorker正在ProgressChanged快速排队事件,每次调用Application.DoEvents()将通过消息队列,来到ProgressChanged事件,更新进度,调用Application.DoEvents(),通过消息队列工作,来到ProgressChanged事件等等.异议导致递归行为你的代码.
尝试删除该呼叫,看看问题是否消失.
Application.DoEvents()
Run Code Online (Sandbox Code Playgroud)
那是麻烦制造者.您添加它是因为您注意到即使您使用了BGW,用户界面仍然会冻结.问题是,当它抽出事件时,您的BGW再次调用了ReportProgress.导致ProgressChanged再次运行.导致DoEvents再次被调用.这可能会持续几秒钟,直到ui线程耗尽堆栈空间.KABOOM.
您必须删除DoEvents()调用.并且解决了真正的问题,你的BGW 经常调用ReportProgress 方式.导致ui线程被调用请求调用ProgressChanged.导致它不再负责其常规职责.包括绘画和响应用户输入.
调用ReportProgress每秒不超过20次.人眼看起来很光滑.收集计算结果,这样您就可以准备好处理一大堆工作了.如果你的工作者产生的结果比ui线程可以显示的速度快,那么你别无选择,只能强行减速.