我有这个代码循环遍历我列表中的所有帐户,然后使用每个帐户的任务作为加速流程的方法对帐户执行某些操作。每次程序完成此操作时,我希望用户界面更新进度条。我之前使用的是Invoke,但它不是最好的选择而且我无法使用它。现在我知道这可以使用后台工作程序完成,但这不是使应用程序成为多线程的最佳方法,所以我使用了它。而不是调用我听说ContinueWith,但我似乎无法让它工作,我得到没有错误信息只是一个红色下划线。 代码:
progressBar.Value = 0
Dim tasks As New List(Of Task)()
For Each account In combos
Dim t As Task = Task.Run(Sub()
While checked = False
If proxies.Count = 0 Then
Exit Sub
'Also can't think of a good way to stop searching through accounts when there are no proxies left in my queue.
End If
Dim proxy As New WebProxy(proxies(0))
proxies.TryDequeue(0)
'Do something
End While
checkedAmount += 1
Dim progress As Integer = ((checkedAmount / combos.Count) * 100)
Task.ContinueWith(progressBar.Value = progress, TaskScheduler.FromCurrentSynchronizationContext()) 'Error here
End Sub)
tasks.Add(t)
Next
Task.WaitAll(tasks.ToArray())
我还试过把一个子物品和东西放在一起,但这些都没有结果。 感谢您提前提供任何帮助。
使用invoke尝试更新:
Private Delegate Sub UpdateProgressBarDelegate(ByVal progressBarUpdate As ProgressBar, ByVal value As Integer)
Dim checkedAmount As Integer = 0
Dim checked As Boolean = False
Private Sub startBtn_Click(sender As Object, e As EventArgs) Handles startBtn.Click
progressBar.Value = 0
Dim tasks As New List(Of Task)()
For Each account In combos
Dim t As Task = Task.Run(Sub()
While checked = False
proxies.TryDequeue(0)
'do stuff
End While
checkedAmount += 1
Dim progress As Integer = ((checkedAmount / combos.Count) * 100)
If Me.InvokeRequired = True Then
Me.Invoke(New UpdateProgressBarDelegate(AddressOf UpdateProgressBar), progressBar, progress)
Else
UpdateProgressBar(progressBar, progress)
End If
'Task.ContinueWith(progressBar.Value = progress, TaskScheduler.FromCurrentSynchronizationContext())
End Sub)
tasks.Add(t)
Next
Task.WaitAll(tasks.ToArray())
End Sub
Private Sub UpdateProgressBar(ByVal ProgressBarUpdate As ProgressBar, progress As Integer)
progressBar.Value = progress
End Sub
仍然不确定为什么?
答案 0 :(得分:3)
现在我知道这可以使用后台工作程序来完成,但这不是使应用程序成为多线程的最佳方法
排序。
BackgroundWorker是一种单独运行许多不同任务的糟糕方法。没有人愿意为每个任务处理单独的BackgroundWorker组件。但一个 BackgroundWorker是一种伟大的方法,只能产生一个额外的线程来管理所有其他任务并更新进度条。这是一个简单的解决方案。
无论哪种方式,您要做的一件事就是移动代码以更新各个任务中的ProgressBar。在任务中包含这些内容会违反关注点分离 1 。完成后,您还需要将调用更改为WaitAll()
,以便在知道您拥有多少任务的循环中使用WaitAny()
,这样您仍然可以在每个任务完成时更新ProgressBar。这也将导致修复当前问题的副作用。
Private Async Sub startBtn_Click(sender As Object, e As EventArgs) Handles startBtn.Click
Dim tasks As New List(Of Task)()
For Each account In combos
Dim t As Task = Task.Run(Sub()
While Not checked
proxies.TryDequeue(0)
'do stuff
End While
End Sub)
tasks.Add(t)
Next
progressBar.Value = 0
For i As Integer = 1 To tasks.Count
Dim t = Await Task.WhenAny(tasks)
tasks.Remove(t)
progressBar.Value = (i / combos.Count) * 100
Next i
End Sub
1这里的问题说明了我们关心问题分离的一个原因。一旦我解决了这个问题,代码变得很多更简单,令人沮丧的错误就会消失。