私は単純なスレッド アプリケーションをコーディングしています。開始ボタンをクリックすると、アプリケーションはこのボタンを無効にし、For iterations を作成して 5 つの ProgressBars を更新するだけで 5 つのスレッドを実行します。最後のスレッドは、スレッドの終了を待って、開始ボタンを再度有効にします。
問題: プログレスバーが 100% になる前にボタンが有効になっているのが表示されます... プログレスバーはまだ更新中です!
どうしたの?UI スレッドで結合ステートメントを作成する方法はありますか?
コードは次のとおりです。
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 が中央にあるときにボタンを有効にするよりも本当に優れています:)