gpt4 book ai didi

vb.net - 点网 : Is there a way to do a Join statement on the UI Thread?

转载 作者:行者123 更新时间:2023-12-02 01:49:29 25 4
gpt4 key购买 nike

我正在编写一个简单的线程应用程序:当单击开始按钮时,应用程序禁用此按钮,运行 5 个线程,简单地进行迭代并更新 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 位于中间时启用按钮要好:)

最佳答案

好的,我做了一些测试,发现问题出在进度条动画上。在您的按钮启用时(这是正确的),进度条仍处于“动画模式”。这可以通过禁用 XP visual styles 来验证.

进度条有一个属性名MarqueeAnimationSpeed , 但不幸的是,这在使用 Blocks 样式时无效。

我进行了谷歌搜索并找到了这篇 SO 帖子:

Disabling .NET progressbar animation when changing value?

示例应用程序

Imports System.Threading
Imports System.Threading.Tasks

Public Class Form1

Public Sub New()
Me.InitializeComponent()
Me.StartButton = New Button() With {.TabIndex = 0, .Dock = DockStyle.Top, .Text = "Start", .Height = 30}
Me.ProgressBar1 = New ProgressBar With {.TabIndex = 1, .Dock = DockStyle.Top, .Height = 30, .Name = "ProgressBar1"}
Me.ProgressBar2 = New ProgressBar With {.TabIndex = 2, .Dock = DockStyle.Top, .Height = 30, .Name = "ProgressBar2"}
Me.ProgressBar3 = New ProgressBar With {.TabIndex = 3, .Dock = DockStyle.Top, .Height = 30, .Name = "ProgressBar3"}
Me.ProgressBar4 = New ProgressBar With {.TabIndex = 4, .Dock = DockStyle.Top, .Height = 30, .Name = "ProgressBar4"}
Me.ProgressBar5 = New ProgressBar With {.TabIndex = 5, .Dock = DockStyle.Top, .Height = 30, .Name = "ProgressBar5"}
Me.Controls.AddRange({Me.ProgressBar5, Me.ProgressBar4, Me.ProgressBar3, Me.ProgressBar2, Me.ProgressBar1, Me.StartButton})
End Sub

Private Sub HandleStartButtonClicked(sender As Object, e As EventArgs) Handles StartButton.Click

Me.StartButton.Enabled = False

Dim tasks As Task() = New Task(4) {}

For i As Integer = 0 To 4
Dim index As Integer = i
tasks(i) = New Task(
Sub()
Dim n As Integer = rnd.Next(100, 1001)
For j As Integer = 0 To n
Me.Invoke(
Sub()
DirectCast(Me.Controls("ProgressBar" & (index + 1).ToString()), ProgressBar).Value = CInt((j / n) * 100.0#)
End Sub
)
Thread.Sleep(10)
Next
End Sub
)
Next

Task.Factory.ContinueWhenAll(tasks,
Sub() Me.Invoke(
Sub()
MessageBox.Show(String.Join(Environment.NewLine, From pb As ProgressBar In Me.Controls.OfType(Of ProgressBar)() Select (pb.Name & ": " & pb.Value.ToString())))
Me.StartButton.Enabled = True
End Sub
)
)

Array.ForEach(Of Task)(tasks, Sub(t) t.Start())

End Sub

Private WithEvents StartButton As Button
Private WithEvents ProgressBar1 As ProgressBar
Private WithEvents ProgressBar2 As ProgressBar
Private WithEvents ProgressBar3 As ProgressBar
Private WithEvents ProgressBar4 As ProgressBar
Private WithEvents ProgressBar5 As ProgressBar
Private Shared rnd As New Random()

End Class

关于vb.net - 点网 : Is there a way to do a Join statement on the UI Thread?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23679542/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com