【发布时间】:2014-07-03 23:27:52
【问题描述】:
我正在编写一个简单的线程应用程序:单击开始按钮时,应用程序禁用此按钮,运行 5 个线程,只需进行 For 迭代并更新 5 个 ProgressBars。最后一个线程正在等待线程结束,以重新启用我的开始按钮。
问题:用户在进度条达到 100% 之前看到按钮已启用...并且进度条仍在更新!
有什么问题?有没有办法在 UI Thread 上做一个 join 语句?
代码如下:
Imports System.Threading
Public Structure ThreadParameters
Public ThreadId As Integer
Public pgBar As ProgressBar
Public iterations As Integer
End Structure
Public Structure SetPgValueParameters
Public pgBar As ProgressBar
Public value As Integer
End Structure
Public Class Form1
Private threads(4) As Thread
Private Shared FormThread As Thread
Private Sub StartButton_Click(sender As Object, e As EventArgs) Handles StartButton.Click
StartButton.Enabled = False
Dim MainThread As Thread = New Thread(AddressOf WaitThreads)
MainThread.Start()
For i = 0 To 4
threads(i) = New Thread(AddressOf ThreadRun)
Dim params As ThreadParameters
params.pgBar = Me.Controls.Find("ProgressBar" & (i + 1), False)(0)
params.iterations = 100
params.ThreadId = i
threads(i).Start(params)
Next
End Sub
Private Sub ThreadRun(params As ThreadParameters)
Dim invokeParams As SetPgValueParameters
Dim lastIntegerVal As Integer = 1
invokeParams.pgBar = params.pgBar
For i = 0 To params.iterations
invokeParams.value = (100 * i / params.iterations)
setPgValue(invokeParams)
Console.WriteLine(params.ThreadId & ":" & i & "/" & params.iterations)
Next
End Sub
Private Delegate Sub setPgValueDelegate(params As SetPgValueParameters)
Private Sub setPgValue(params As SetPgValueParameters)
If params.pgBar.InvokeRequired Then
Dim d As New setPgValueDelegate(AddressOf setPgValue)
Me.Invoke(d, New Object() {params})
Else
params.pgBar.Value = params.value
'Application.DoEvents()
End If
End Sub
Private Sub WaitThreads()
For i = 0 To 4
threads(i).Join()
Next
FormThread.Join()
setButtonEnabled()
End Sub
Private Delegate Sub setButtonEnabledDelegate()
Private Sub setButtonEnabled()
If StartButton.InvokeRequired Then
Dim d As New setButtonEnabledDelegate(AddressOf setButtonEnabled)
Me.Invoke(d, Nothing)
Else
Application.DoEvents()
StartButton.Enabled = True
Console.WriteLine("Bouton réactivé")
End If
End Sub
End Class
编辑:感谢 Bjørn-Roger Kringsjå 的链接。所以有一个解决方法:增加和直接减少值跳过动画。对于最大值,将其设置为最大值,减少1,增加1... 还是有一点点延迟,但确实比在 ProgressBars 在中间时启用按钮要好:)
【问题讨论】:
-
我强烈建议您拒绝(如果可能)这种“过时”的方法,而改用 Task 类。
标签: vb.net multithreading user-interface synchronisation