2017-10-12 14 views
-2

Ich habe diesen Code, der alle meine Konten in meiner Liste durchläuft und dann etwas mit den Konten erledigt, die Aufgaben für jedes Konto verwenden, um den Prozess zu beschleunigen. Jedes Mal, wenn das Programm diese Aktion beendet, möchte ich, dass die Benutzeroberfläche den Fortschrittsbalken aktualisiert. Ich habe Invoke vorher verwendet, aber es ist nicht die beste Option und ich konnte es nicht zum Laufen bringen. Jetzt weiß ich, dass dies mit einem Hintergrund-Worker erledigt werden kann, aber das ist nicht der beste Weg, um Ihre Anwendung Multithread zu machen, also habe ich das verwendet. Und anstatt zu rufen, habe ich von ContinueWith gehört, aber ich kann es scheinbar nicht funktionieren lassen und bekomme keine Fehlermeldung, nur eine rote Unterstreichung. Code:VB.net 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()) 

bekomme ich keinen Fehlercode wie hier gezeigt: enter image description here

ich auch nach und so versucht habe, eine Unter setzen, aber diese führen zu nichts. Danke für jede Hilfe im Voraus.

-Update versucht, mit 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 

Immer noch nicht nicht sicher funktioniert, warum?

+1

'Ich habe Invoke vorher verwendet, aber es ist nicht die beste Option '- Uhhh, ja, ist es. Es ist eine der wenigen Möglichkeiten (oder vielleicht sogar die einzige Möglichkeit), mit denen Sie Aufrufe an den UI-Thread vermitteln können. - Auch, FYI, 'Task.ContinueWith()' erfordert auch, dass Sie aufrufen, da es auch eine Hintergrund-Task/Thread ausführt. –

+0

Das Aufrufen muss jedoch nicht so kompliziert sein! Sie können eine Erweiterungsmethode schreiben, die alles für Sie erledigt, sodass Sie nur eine Zeile ** zum Aufrufen benötigen. Siehe diese Antwort von mir für weitere Informationen über das Aufrufen, und wie Sie es vereinfachen können (von _ ** Zugriff auf den UI-Thread ** _): https://Stackoverflow.com/a/45571728/3740093 –

+0

Ok, ich habe dies Code jetzt, aber es funktioniert nicht einmal richtig? Wie es nicht aktualisiert wird, noch läuft es im Hintergrund. – 1ben99

Antwort

2

Jetzt weiß ich, das einen Hintergrund Arbeiter getan werden kann, verwenden, aber dies ist nicht der beste Weg, um Ihre Anwendung

Sortieren von multithreaded machen.

BackgroundWorker ist eine schlechte Möglichkeit, viele verschiedene Aufgaben einzeln auszuführen. Niemand möchte mit einer separaten BackgroundWorker-Komponente für jede Aufgabe arbeiten. Aber ein BackgroundWorker ist eine große Möglichkeit, nur einen zusätzlichen Thread zu spawnen, um alle Ihre anderen Aufgaben zu verwalten und den Fortschrittsbalken zu aktualisieren. Es ist eine einfache Lösung hier.

In jedem Fall sollten Sie den Code verschieben, um die ProgressBar aus den einzelnen Aufgaben zu aktualisieren. Wenn das in einem Aufgabenbereich verletzt wird, wird die Trennung von Bedenken . Sobald Sie das getan haben, müssen Sie auch den Aufruf an WaitAll() ändern, um WaitAny() in einer Schleife zu verwenden, die weiß, wie viele Aufgaben Sie haben, damit Sie die ProgressBar weiterhin aktualisieren können, wie jede Aufgabe beendet wird. Dies hat den Nebeneffekt, Ihr aktuelles Problem zu beheben.

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 Das Problem hier zeigt einen Grund, warum wir überhaupt über die Trennung von Bedenken sorgen. Sobald ich das beheben, wird der Code viel einfacher und die frustrierenden Fehler einfach weg.

+0

Ich weiß Ihre Eingabe zu schätzen, aber ich würde es am liebsten tun, indem ich zumindest einen Hintergrundarbeiter benutze, der langsamer ist und meine Benutzeroberfläche bei der Ausführung der Aufgaben sehr lückenhaft und fehlerhaft macht. – 1ben99

+0

+1 für die Bearbeitung. Ich hatte vergessen, dass der 'Task.WaitAll()' Aufruf den UI-Thread einfriert (das heißt, wenn er nicht mit 'Await' aufgerufen wurde). –

+1

@VisualVincent Oh, das macht er wahrscheinlich immer noch. Diese Leiste ruft eine Art von WaitX() in einem UI-Thread auf. Deshalb sollte er dies zu einem BackgroundWorker verschieben. Aber das bringt die Dinge zumindest in die richtige Richtung. –

Verwandte Themen