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!
我正在尝试使用 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!