TonyW TonyW - 5 months ago 11
Vb.net Question

Tasks aren't coming in the order I need them to

I'm having a small issue with tasks.. below is a screenshot of a simple example of what I'm doing. I want the ThirdJob to show up first, then SecondJob, then FirstJob (or whatever order I'm doing it in).

enter image description here

I click the dropdown box, and it adds tasks to listbox1... then I press the button, and it executes those tasks based on a list(of task).

I have a 1000 MS delay on the ThirdJob, so of course, it comes in last. How do I make it so they come in the order I want them to, no matter how long it takes.

Current code I'm using to do this..

Dim tasklist As New List(Of Task)

Private Async Sub Button_Click(sender As Object, e As RoutedEventArgs)

For Each item In tasklist
'item.RunSynchronously()
item.Start()
Next

Await Task.WhenAll(tasklist.ToArray)

End Sub

Public Sub FirstJob()
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, DirectCast(Function() listbox2.Items.Add("FirstJob"), Action))
End Sub
Public Sub SecondJob()
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, DirectCast(Function() listbox2.Items.Add("SecondJob"), Action))
End Sub
Public Sub ThirdJob()
Thread.Sleep(1000)
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, DirectCast(Function() listbox2.Items.Add("ThirdJob"), Action))
End Sub

Private Sub ComboBox_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)

listbox1.Items.Add(cb1.SelectedItem)
If cb1.SelectedItem.ToString = "FirstJob" Then
tasklist.Add(New Task(Sub() FirstJob()))
ElseIf cb1.SelectedItem.ToString = "SecondJob" Then
tasklist.Add(New Task(Sub() SecondJob()))
ElseIf cb1.SelectedItem.ToString = "ThirdJob" Then
tasklist.Add(New Task(Sub() ThirdJob()))
End If

End Sub

Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
cb1.Items.Add("FirstJob")
cb1.Items.Add("SecondJob")
cb1.Items.Add("ThirdJob")
End Sub


I'm sure the issue lies in how I'm doing my for loop though my array.

If I change

For Each item In tasklist
item.Start()
Next

Await Task.WhenAll(tasklist.ToArray)


to

For Each item In tasklist
item.Start()
item.wait
Next


It goes in order, but freezes the UI, which I don't want. Any ideas?

Answer

How about creating a custom method and utilizing the Task.ContinueWith() method to start the tasks after each other?

Public Class TaskHelper
    Public Shared Function RunAllSequential(ByVal Tasks() As Task) As Task
        For i = 0 To Tasks.Length - 2 'Using -2 since the last task don't need to start another one.
            Tasks(i).ContinueWith(Sub() Tasks(i + 1).Start())
        Next

        Tasks(0).Start() 'Start the first task.

        Return Task.WhenAll(Tasks)
    End Sub
End Class

This will run the specified tasks after each other. When the first one is done the second one will be started, and so on.

Example use:

Await TaskHelper.RunAllSequential(tasklist.ToArray())
Comments