我对vb.net中的进度栏很困惑,这是我的代码
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ProgressBar_my.Minimum = 0
ProgressBar_my.Maximum = 10
ProgressBar_my.Step = 1
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ProgressBar_my.PerformStep()
Threading.Thread.Sleep(5000)
If 1 = 1 Then
ProgressBar_my.PerformStep()
ProgressBar_my.PerformStep()
End If
'Threading.Thread.Sleep(2000)
End Sub
对于上述代码,我期望的是,在我单击Button1
之后,进度栏将增加进度状态1,然后将其暂停5 sec
,然后它将一次将进度状态增加2个。
但是,在我运行上述代码后,我看到的是,在我单击Button1
之后,进度栏将在5 sec
之后连续增加3个。
有人可以告诉我为什么这样的行为,我应该如何编程我的代码,以便我可以增加1个,然后暂停5秒,然后增加2?
预先感谢!
我认为您看到的(或看不到)是进度栏需要有限的时间来促进每个步骤的事实。
当您在UI线程上调用Threading.Thread.Sleep
时,这会阻止进度栏重新绘制到Sleep
您应该做的是更新背景工人的进度栏,然后我想您会看到自己想要的效果。
在您的表格中添加一个背景工作者
更改按钮单击代码以启动工人:
Private Sub frmSO_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ProgressBar_my.Minimum = 0
ProgressBar_my.Maximum = 10
ProgressBar_my.Step = 1
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
BackgroundWorker1.RunWorkerAsync
End Sub
然后在Dowork事件中执行更新:
'define a delegate to handle updates to the UI thread
Private Delegate Sub PerformStepCallback()
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim cb As PerformStepCallback = AddressOf ProgressBar_my.PerformStep
Me.BeginInvoke(cb)
Threading.Thread.Sleep(5000)
Me.BeginInvoke(cb)
Me.BeginInvoke(cb)
End Sub
问题是您调用Threading.Thread.Sleep(5000)
,它将暂停当前线程。但这也意味着窗口不会被重新绘制,因此您只有在线程不再暂停之后才能看到第一个调用PerformStep
的效果。
您可以使用另一个线程进行等待和第二个更新;在这种情况下,最简单的方法是使用任务并行库:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ProgressBar1.PerformStep()
Task.Delay(5000).ContinueWith(Sub()
ProgressBar1.PerformStep()
ProgressBar1.PerformStep()
End Sub, TaskScheduler.FromCurrentSynchronizationContext)
End Sub
感谢马特·威尔科(Matt Wilko)给我的线索。这是我的代码。
从工具箱的"组件"选项卡中,添加一个名为backgroundWorker2
的BackgroundWorker
组件。为BackgroundWorker
创建DoWork
和ProgressChanged
事件处理程序。
以下代码将启动组件。
Public Sub New()
InitializeComponent()
BackgroundWorker2.WorkerReportsProgress = True
BackgroundWorker2.WorkerSupportsCancellation = True
End Sub
在单击按钮并且背景工人未运行时致电RunWorkerAsync
。
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If BackgroundWorker2.IsBusy <> True And ProgressBar_my.Value < 6 Then
BackgroundWorker2.RunWorkerAsync()
End If
End Sub
Private Sub BackgroundWorker2_DoWork_1(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles BackgroundWorker2.DoWork
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
worker.ReportProgress(1)
System.Threading.Thread.Sleep(2000)
worker.ReportProgress(1)
worker.ReportProgress(1)
End Sub
每次调用ReportProgress
方法时,都会提出以下事件。
Private Sub backgroundWorker2_ProgressChanged(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
Handles BackgroundWorker2.ProgressChanged
ProgressBar_my.PerformStep()
End Sub
有关BackgroundWorker
的更多信息:http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v = vs.110).aspx