简体   繁体   中英

VB.net - Progressbar using BackgroundWorker

I am trying to implement a progressbar using BackgroundWorker.

But the progress bar hides itself after a second and it doesn't remain on top till end. Not sure why.

Below is my code in form:

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

And below is my code in for which contains progressbar:

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

You don't need the AutoReset event as you can handle the RunWorkerCompleted event. Currently you are blocking the UI thread.

Remove the msgbox from RunWorkerAsync as well as this should be handled on your ui thread.

I suspect its an exception that is causing the RunWorkerAsync to exit so inspect the error code in the RunWorkerCompleted event. This is probably caused by your TaskInProgress property which through a roundabout way is interacting with the textbox despite being on the Background thread.

Instead to update the TaskInProgress textbox send it as the extra argument to ReportProgress and get it back from the progress box.

BackgroundWorker.ReportProgress(33, "Hello")

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

Below is the corrected code which worked very well:

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM