VB.net ContinueWith

时间:2017-10-12 19:22:07

标签: vb.net multithreading user-interface task continuewith

我有这个代码循环遍历我列表中的所有帐户,然后使用每个帐户的任务作为加速流程的方法对帐户执行某些操作。每次程序完成此操作时,我希望用户界面更新进度条。我之前使用的是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())

我没有得到错误代码,如下所示: enter image description here

我还试过把一个子物品和东西放在一起,但这些都没有结果。 感谢您提前提供任何帮助。

使用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

仍然不确定为什么?

1 个答案:

答案 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这里的问题说明了我们关心问题分离的一个原因。一旦我解决了这个问题,代码变得很多更简单,令人沮丧的错误就会消失。