我正在开发一个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库。更少的代码,更容易调试,我实际上让它工作,所以赢,赢,赢。
答案 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