【问题标题】:Multithreading for a progressbar and code locations (vb.net)?进度条和代码位置的多线程(vb.net)?
【发布时间】:2012-09-21 15:19:32
【问题描述】:

我无法从不同的线程更新进度条。 我确实让它以最简单的方式运行,但是清理代码让我卡住了。

我的测试代码看起来像网络上所有与 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线程,不管这个线程调用的是什么类的代码…… 好像不是这样?

感谢您的任何想法。

【问题讨论】:

  • 您需要停止使用表单的类型名称,就好像它是一个对象引用一样。 FormP.SetProgress(i, 10) 语句调用 FormP 的 new 实例上的方法,而不是用户正在查看的实例。
  • 非常感谢您……我以前对表单的实例/类名称异常有过奇怪的感觉,但从未冒险研究它。现在它可以工作了,对我来说一切都很好......!

标签: vb.net multithreading progress-bar backgroundworker invokerequired


【解决方案1】:

最终效果如何:

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 中的 Progress-Dialog-Code:

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

【讨论】:

    猜你喜欢
    • 2011-06-21
    • 1970-01-01
    • 2020-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多