Fiona
Fiona

Reputation: 1599

vb.net Not waiting until all tasks have completed

So I'm processing records. I'm using a task to process each record. My issue is that my program is completing before all tasks complete. Anyone any thoughts on what I'm doing wrong here?

        Dim task As Task

        Try
            'Keep looping until no more requests to run have been made            
            Do
                Dim controller As New Controller()
                Dim record As Record = controller.GetNextRecord()

                If record IsNot Nothing Then

                    'Use Task!
                     task = Task.Factory.StartNew(Sub() controller.ProcessRecord(record), TaskCreationOptions.LongRunning)
                     CalledWhenBusy = True
                End If
        TryAgain:
            Loop Until ProcessAgain() = False


        Catch ex As System.Net.WebException
            logger.ErrorException("unable to connect to remoting server", ex)

        Finally
            logger.Info("Processed all records.. now about to wait for all tasks to complete")
            'Wait till all tasks have stopped running
            Task.WaitAll(task)

            logger.Info("Processed all records.. All tasks have completed")
            'The dispatcher has finished for now so clean up
            Me.StopUsing()
        End Try




Private Function ProcessAgain() As Boolean

    If CalledWhenBusy Then
        'Reset the flag and exit with true
        CalledWhenBusy = False
        Return True
    End If

    Return False

End Function

UPDATE

I've resolved my issue by using a list of tasks as suggested by @HansPassant and @usr

The reason for not using Foreach, is that more records can be added while processing.. hence the do while loop...

Thank you for your help.

            Dim taskList = New List(Of Task)()

        Try
            'Keep looping until no more requests to run have been made            
            Do
                Dim controller As New Controller()
                Dim record As Record = controller.GetNextRecord()

                If record IsNot Nothing Then

                    'Use Task!
                    taskList.Add(Task.Factory.StartNew(Sub() controller.ProcessRecord(record)))
                    CalledWhenBusy = True
                End If
TryAgain:
            Loop Until ProcessAgain() = False


        Catch ex As System.Net.WebException
            logger.ErrorException("unable to connect to remoting server", ex)

        Finally
            logger.Info("Processed all records.. now about to wait for all tasks to complete")
            'Wait till all tasks have stopped running
            Task.WaitAll(taskList.ToArray())

            logger.Info("Processed all records.. All tasks have completed")
            'The dispatcher has finished for now so clean up
            Me.StopUsing()
        End Try

Upvotes: 0

Views: 1274

Answers (1)

usr
usr

Reputation: 171246

Task.WaitAll(task) is just waiting for one task. Where are the others? Did you even store them? Not apparent from this code.

Ideally, you transform this code so that it can make use of Parallel.ForEach. You need to put the work items into IEnumerable format for that to work. For example, add them to a List and feed the list to Parallel.ForEach.

Upvotes: 2

Related Questions