VB.net - 使用 BackgroundWorker 的进度条

VB.net - Progressbar using BackgroundWorker

我正在尝试使用 BackgroundWorker 实现进度条。

但是进度条会在一秒钟后自行隐藏,并且不会一直保持在顶部直到结束。不知道为什么。

下面是我的代码形式:

Private Sub btnProgressBarPOC_Click(sender As Object, e As EventArgs) Handles btnProgressBarPOC.Click
    BackgroundWorker = New BackgroundWorker()
    BackgroundWorker.WorkerReportsProgress = True
    autoResetEvent = New AutoResetEvent(False)
    ProgressBar = New frmProgressBar(BackgroundWorker)
    ProgressBar.ShowDialog()

    autoResetEvent.WaitOne()
    MsgBox("Main Done", vbInformation)
End Sub

Sub Processing() Handles BackgroundWorker.DoWork
    BackgroundWorker.ReportProgress(33)
    Threading.Thread.Sleep(5000)

    BackgroundWorker.ReportProgress(66)
    Threading.Thread.Sleep(5000)

    BackgroundWorker.ReportProgress(100)

    MsgBox("Background Done", vbInformation)
    AutoResetEvent.Set()
End Sub

下面是我的代码,其中包含进度条:

Imports System.ComponentModel

Public Class frmProgressBar

    Private WithEvents _BGW As System.ComponentModel.BackgroundWorker
    Private _TaskInProgress As String

    Public WriteOnly Property TaskInProgress()
        Set(value)
            _TaskInProgress = value
            _BGW.ReportProgress(1)
        End Set
    End Property

    Public Sub New(ByVal BGW As System.ComponentModel.BackgroundWorker)
        _BGW = BGW
        InitializeComponent()
    End Sub

    Private Sub frmProgress_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
        If Not IsNothing(_BGW) Then
            _BGW.RunWorkerAsync()
        End If
    End Sub

    Private Sub _BGW_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles _BGW.ProgressChanged
        progressBar.Value = e.ProgressPercentage

        If Me.Text <> _TaskInProgress Then
            Me.Text = _TaskInProgress
        End If
    End Sub

    Private Sub _BGW_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles _BGW.RunWorkerCompleted
        Me.Close()
        _TaskInProgress = ""
    End Sub

    'Private Sub _BGW_DoWork(sender As Object, e As DoWorkEventArgs) Handles _BGW.DoWork
    '    Do While True
    '        ' Has the background worker be told to stop?
    '        If _BGW.CancellationPending Then
    '            ' Set Cancel to True
    '            e.Cancel = True
    '            Exit Do
    '        End If
    '        System.Threading.Thread.Sleep(2000) ' Sleep for 1 Second
    '    Loop
    'End Sub
End Class

I have uploaded my project here: https://drive.google.com/file/d/0B7gzonuQsNbvaDZvR3ltSl9WNTg/view?usp=sharing

您不需要 AutoReset 事件,因为您可以处理 RunWorkerCompleted 事件。目前您正在阻止 UI 线程。

从 RunWorkerAsync 中删除消息框,这应该在您的 ui 线程上处理。

我怀疑是导致 RunWorkerAsync 退出的异常,因此请检查 RunWorkerCompleted 事件中的错误代码。这可能是由您的 TaskInProgress 属性 引起的,它通过迂回的方式与文本框交互,尽管它在后台线程上。

而不是更新 TaskInProgress 文本框,将其作为额外参数发送给 ReportProgress 并从进度框中取回。

BackgroundWorker.ReportProgress(33, "Hello")

Private Sub _BGW_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles _BGW.ProgressChanged
    Me.Text = CStr(e.UserState)
     ....

下面是更正后的代码,效果很好:

Public Class frmMisc
    Private WithEvents BackgroundWorker As BackgroundWorker, ProgressBar As frmProgressBar

    Private Sub btnProgressBarPOC_Click(sender As Object, e As EventArgs) Handles btnProgressBarPOC.Click
        Call RunProcessing()

        MsgBox("Main Done", vbInformation)
    End Sub

    Sub RunProcessing()
        BackgroundWorker = New BackgroundWorker()
        BackgroundWorker.WorkerReportsProgress = True
        ProgressBar = New frmProgressBar(BackgroundWorker)
        ProgressBar.ShowDialog()
    End Sub

    Sub Processing() Handles BackgroundWorker.DoWork
        BackgroundWorker.ReportProgress(33, "Step-1")
        Threading.Thread.Sleep(3000)

        BackgroundWorker.ReportProgress(66, "Step-2")
        Threading.Thread.Sleep(2000)

        BackgroundWorker.ReportProgress(100, "Step-3")
    End Sub
End Class

Public Class frmProgressBar

    Private WithEvents _BGW As System.ComponentModel.BackgroundWorker
    Private _TaskInProgress As String

    Public Sub New(ByVal BGW As System.ComponentModel.BackgroundWorker)
        _BGW = BGW
        InitializeComponent()
    End Sub

    Private Sub frmProgress_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
        If Not IsNothing(_BGW) Then
            _BGW.RunWorkerAsync()
        End If
    End Sub

    Private Sub _BGW_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles _BGW.ProgressChanged
        progressBar.Value = e.ProgressPercentage

        Me.Text = e.UserState
    End Sub

    Private Sub _BGW_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles _BGW.RunWorkerCompleted
        Me.Close()
        _TaskInProgress = ""
    End Sub
End Class

I was doing up Me.Text outside of ProgressChanged even which was causing this issue. Thanks to @Hans for providing hint about this!