背景工作者ReportProgress没有解雇2

时间:2017-07-06 18:06:11

标签: vb.net winforms

我正在开发一个Legacy应用程序,这让我发疯,我所看到的解决这个问题的每个例子似乎都在做我正在做的事情但由于某种原因我的reportProgress事件拒绝解雇:

Private _worker as BackgroundWorker

Private Sub btnEditCheckSymbol_Click (ByVal sender As Object, ByVal e As EventArgs) Handles btnEditCheckSymbol.Click
    _worker = new BackgroundWorker()
    _worker.WorkerSupportsCancellation = True
    _worker.WorkerReportsProgress = True
    AddHandler _worker.DoWork, AddressOf worker_DoWork
    AddHandler _worker.ProgressChanged, AddressOf worker_ProgressChanged
    AddHandler _worker.RunWorkerCompleted, AddressOf worker_RunWorkerCompleted
    _worker.RunWorkerAsync()

   'Other long running code

   If _worker.IsBusy Then
       _worker.CancelAsync()
   End If
End Sub

Private Sub worker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
    For i As Integer = 60 To 0 step -1
        If _worker.CancellationPending Then
            e.Cancel = True
            return
        End If
        _worker.ReportProgress(i)     
    Next
End Sub

Private Sub worker_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) _
    lbEditCheckSymbol.Invoke(
    Sub ()
        with lbEditCheckSymbol
            .Items.Clear()
            .Items.Add("Please wait for results: " + e.ProgressPercentage)
        end With
    End Sub)
    Thread.Sleep(100)
End Sub

Private Sub worker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
    with lbEditCheckSymbol
        .Items.Clear()
        If Not e.Cancelled then
            lbEditCheckSymbol.Invoke(
                Sub ()
                    with lbEditCheckSymbol
                        .Items.Add("Results should have arrived by now... um wait some more?")
                    end With
                End Sub)
        End If
    end With
End Sub

DoWork被调用,它通过循环烧掉,从不调用ProgressChanged事件,我检查了调试器并注册了ProgressChanged。我主要在C#工作,所以我在这里错过了一些VB voodoo吗?

更新
我放弃了后台工作者的使用,转而使用TPL库。更少的代码,更容易调试,我实际上让它工作,所以赢,赢,赢。

1 个答案:

答案 0 :(得分:0)

如果您的线程工作周围有更好的错误处理程序,当后台线程尝试访问前台线程上的对象时,您将捕获访问冲突。要跨越这样的线程,您需要一些代理并使用BeginInvoke代替Invoke来调用正确的线程。

这段代码可能不完美,但它应该非常接近

Private _worker as BackgroundWorker

Public Delegate Sub ProgressChangedDelegateType(percent As Integer)
Public Delegate Sub RunWorkerCompletedDelegateType(cancelled As Boolean)

Private progressChangedDelegate As ProgressChangedDelegateType
Private runWorkerCompletedDelegate AS RunWorkerCompletedDelegateType

Public Sub Form_Load()
    'bind your delegates in your form load event or in the class constructor
    progressChangedDelegate = AddressOf ProgressChanged
    runWorkerCompletedDelegate = AddressOf RunWorkerCompleted

    'and all of your other stuff in your form_load() event handler...
End Sub

Private Sub btnEditCheckSymbol_Click (ByVal sender As Object, ByVal e As EventArgs) Handles btnEditCheckSymbol.Click
    _worker = new BackgroundWorker()
    _worker.WorkerSupportsCancellation = True
    _worker.WorkerReportsProgress = True
    AddHandler _worker.DoWork, AddressOf worker_DoWork
    AddHandler _worker.ProgressChanged, AddressOf worker_ProgressChanged
    AddHandler _worker.RunWorkerCompleted, AddressOf worker_RunWorkerCompleted
    _worker.RunWorkerAsync()

   'Other long running code

   If _worker.IsBusy Then
       _worker.CancelAsync()
   End If
End Sub

Private Sub worker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
    For i As Integer = 60 To 0 step -1
        If _worker.CancellationPending Then
            e.Cancel = True
            return
        End If
        _worker.ReportProgress(i)     
    Next
End Sub

Private Sub worker_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) 
    If lbEditCheckSymbol.InvokeRequired Then
        BeginInvoke(progressChangedDelgate, {e.ProgressPercentage})
    Else
        ProgressChanged(e.ProgressPercentage)
    End If
End Sub

Public Sub ProgressChanged(percent As Integer)
    Try
        with lbEditCheckSymbol
            .Items.Clear()
            .Items.Add("Please wait for results: " + percent.ToString())
        end With
        DoEvents() 'forces a UI update
    Catch Ex As Exception
        Debug.WriteLine(ex.message) 'put a breakpoint here, just in case
    End Try
    Thread.Sleep(100)
End Sub

Private Sub worker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
    If lbEditCheckSymbol.InvokeRequired Then
        BeginInvoke(runWorkerCompletedDelegate, {e.Cancelled})
    Else
        RunWorkerCompleted(e.Cancelled)
    End If
End Sub

Public Sub RunWorkerCompleted(cancelled As Boolean)
    Try
        with lbEditCheckSymbol
            .Items.Clear()
            If Not cancelled then
                .Items.Add("Results should have arrived by now... um wait some more?")
        end With
        DoEvents() 'Forces a UI update
    Catch Ex As Exception
        Debug.WriteLine(ex.message) 'put a breakpoint here, just in case
    End Try
End Sub