Kallol
Kallol

Reputation: 364

Detecting errors in tasks and reviving

I need to run, lets say, 20 parallel tasks. The task function that is being called is a long running function and can generate errors. I wanted to detect that from the caller and revive the task.

While I understand that handling the exception "inside the task" and rerunning the task is a solution, I was also thinking if there are means to detect this from the caller itself and run the failing task again. When I revive the task it should fall under the bucket of 20 tasks running so that the calling process continues to wait for all the tasks running including the new revived task via Await Task.WhenAll(tasks)

Here is the code on the caller side that creates 20 different task and waits for all of them to finish.

    Try
        watch = New Stopwatch
        watch.Start()
        cs = New CancellationTokenSource
        Timer1.Enabled = True
        Dim tasks = Enumerable.Range(1, 20).Select(Function(i) Task.Run(Function() GetAndProcessMessagesAsync(cs.Token)))
        Await Task.WhenAll(tasks)
    Catch ex As Exception
        MsgBox(ex.Message)
        Timer1.Enabled = False
    End Try

PS: I have checked the below links for a solution but did not find something suitable that I could try. But definitely would think another method could be to use the TaskContinuationOptions option but am really not sure how and where that would fit in my code above.

Task Parallel Library - How do you get a Continuation with TaskContinuationOptions.OnlyOnCanceled to Fire?

catching parallel tasks if they stop prematurely

Upvotes: 0

Views: 55

Answers (1)

svick
svick

Reputation: 244777

I think that doing it inside the Task is the best option, but that doesn't mean you have to change GetAndProcessMessagesAsync. The code could look like this:

Async Function RetryAsync(func As Func(Of Task)) As Task
    While True
        Try
            Await func()
        Catch
            ' TODO: don't catch all exceptions all the time
        End Try
    End While
End Function

…

Dim tasks = Enumerable.Range(1, 20).Select(
    Function(i) Task.Run(
        Function() RetryAsync(
            Function() GetAndProcessMessagesAsync(cs.Token))))

Also, if GetAndProcessMessagesAsync is truly asynchronous, you might not need that Task.Run.

Upvotes: 1

Related Questions