2011-09-27 84 views
1

我的程序中有一個搜索功能,它使用後臺工作程序來獲取結果。 Progress changed事件用於使用新項目更新列表視圖。BackgroundWorker中的Stackoverflow錯誤ProgressChanged

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 

而且我得到這個錯誤

An unhandled exception of type 'System.StackOverflowException' occurred in System.Windows.Forms.dll 

我想這一點,但它不會有所作爲

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 

編輯: 哦,如果我只是一步通過代碼,它沒有任何問題。

編輯2:
這裏是BackgroundWorker的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 
+0

我們可以看到堆棧跟蹤嗎? – therealmitchconnors

+0

背景工作者是否在與lstResults相關的事件中被解僱?我們可以看到它被啓動的方法嗎? – therealmitchconnors

+0

你能告訴我們StackTrace嗎? –

回答

6

我認爲這個問題很可能這條線:

Application.DoEvents() 

如果您BackgroundWorker正在排隊ProgressChanged事件足夠快,每次致電Application.DoEvents()都會通過消息隊列工作,來到ProgressChanged事件,更新進度,致電Application.DoEvents(),工作通過m消息隊列,來到一個ProgressChanged事件,等等。本質上導致你的代碼中的遞歸行爲。

嘗試刪除該呼叫並查看問題是否消失。

5
Application.DoEvents() 

這是麻煩製造者。你添加了它,因爲你注意到用戶界面仍然凍結,即使你使用了BGW。問題是,當它抽取事件時,BGW再次調用ReportProgress。導致ProgressChanged再次運行。導致DoEvents再次被調用。這可能需要幾秒鐘,直到UI線程用完堆棧空間。 KABOOM。

您必須刪除DoEvents()調用。並解決真正的問題,您的BGW太頻繁地調用ReportProgress 方式。使用ui線程充滿調用請求來調用ProgressChanged。導致它不再照顧其日常工作。包括繪畫和迴應用戶輸入。

調用ReportProgress的次數不會超過每秒20次。這對人眼看起來很順利。收集計算結果,以便您可以準備處理大量工作。如果你的工作人員產生的結果比UI線程顯示的結果快,那麼你別無選擇,只能強行減慢它的速度。

+1

謝謝你的解釋。這是我多線程的第一次冒險之一,所以這將有所幫助。在將他們傳遞給進度記者之前,我必須先考慮收集了多少人,才能避免陷入困境。 – AndyD273