3

我被困在从不同的线程更新进度条。我确实让它以最简单的方式运行,但随后清理代码让我陷入困境。

我的测试代码看起来像网络上所有与 backgroundworker 和 BeginInvoke 相关的示例。

FormP 是 Progressbar-Form。这有效:

Public Class Form1
Private Delegate Sub delegate_ProgressUpdate(ByVal paramValue As Integer,
  ByVal paramMax As Integer)

Private Sub Button1_Click(sender As System.Object,
  e As System.EventArgs) Handles Button1.Click
    ' Test 01:
    ' Show Progressbar via BGW
    ' All functions are within Form1
    Dim bgw As New BackgroundWorker()
    AddHandler bgw.DoWork, AddressOf BGW_Sample01_DoWork

    FormP.Show(Me)
    bgw.RunWorkerAsync()
End Sub

Private Sub invokeMe_ProgressUpdate(ByVal paramValue As Integer, ByVal paramMax As Integer)
    FormP.ProgressBar1.Maximum = paramMax
    FormP.ProgressBar1.Value = paramValue
    FormP.ProgressBar1.Update()
End Sub

Private Sub BGW_Sample01_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
    For i As Integer = 1 To 10
        Threading.Thread.Sleep(500) ' Test delay
        Me.BeginInvoke(New delegate_ProgressUpdate(AddressOf invokeMe_ProgressUpdate),
                       i, 10)
    Next
    MessageBox.Show("Fertig")
End Sub

如果我试图让事情更有序地封装在 FormP 中,那就行不通了。

Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
    Dim bgw As New BackgroundWorker
    AddHandler bgw.DoWork, AddressOf BGW_Sample02_DoWork
    FormP.Show(Me)
    bgw.RunWorkerAsync()
End Sub

Private Sub BGW_Sample02_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
    For i As Integer = 1 To 10
        Threading.Thread.Sleep(500)
        FormP.SetProgress(i, 10)
    Next
    MessageBox.Show("Fertig")
End Sub


' ########## FormP #################

Public Class FormP

Private Delegate Sub delegate_ProgressUpdate(ByVal value As Integer, ByVal maximum As Integer)

Public Sub SetProgress(ByVal paramValue As Integer, ByVal paramMaximum As Integer)
    If Me.InvokeRequired Then
        Me.Invoke(New delegate_ProgressUpdate(AddressOf Me.SetProgress), paramValue, paramMaximum)
    Else
        Me.ProgressBar1.Maximum = paramMaximum
        Me.ProgressBar1.Value = paramValue
        Me.ProgressBar1.Update()
    End If
End Sub

End Class

FormP 不会冻结,但 UI 不会更新。实际上 Me.InvokeRequired 是错误的,我认为这就是我开始错过一些重要部分的地方。我在这里尝试了 Form1.InvokeRequired,但它也是错误的。我的理解是:这里的调用线程就是bgw线程,不管这个线程调用的是什么类的代码……好像不是这样的吧?

感谢您的任何想法。

4

1 回答 1

2

最终奏效的方法:

Private frmP As FormP

Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
    Dim bgw As New BackgroundWorker
    If Me.frmP IsNot Nothing AndAlso Me.frmP.Visible Then Return
    Me.frmP = New FormP
    Me.frmP.Show(Me)
    AddHandler bgw.DoWork, AddressOf BGW_Sample02_DoWork
    bgw.RunWorkerAsync(New Object() {Me.frmP})
End Sub

Private Sub BGW_Sample02_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
    Dim objFrmP As FormP = DirectCast(e.Argument(0), FormP)
    For i As Integer = 1 To 10
        objFrmP.setProgress(i, 10)
        Threading.Thread.Sleep(500)
    Next
    MessageBox.Show("Finished")
End Sub

FormP 中的进度对话框代码:

Public Sub setProgress(paramValue As Integer, paramMaximum As Integer)
    If Me.InvokeRequired Then
        ' defining a delegate type is not really necessary
        Me.Invoke(Sub() Me.setProgress(paramValue, paramMaximum))
    Else
        Me.ProgressBar1.Maximum = paramMaximum
        Me.ProgressBar1.Value = paramValue
        Me.ProgressBar1.Update()
    End If
End Sub
于 2012-10-27T21:27:41.173 回答