Search code examples
c#taskcontinuations

Restarting task if it fails


I'm trying to restart one of multiple tasks if it fails. Im using .ContinueWith(t => { HandleException(t); }, TaskContinuationOptions.OnlyOnFaulted); where the HandleException(t) method should find the task in the array of excisting tasks and create a new one in its place. Only the task passed to my HandleException(t) method is different from original task so I'm not able to find it in my excisting tasks. Also the excisting task is still running at the time the exception is handled.

Example:

using System;
using System.Threading.Tasks;
using System.Threading;

static Task[] tasks;
static void Main(string[] args)
{
    tasks = new Task[2];
    for (int i = 0; i < tasks.Count(); i++)
    {
        tasks[i] = Task.Run(() => { Thread.Sleep(1000); throw new Exception("BOOM"); })
             .ContinueWith(t => { HandleException(t); }
             , TaskContinuationOptions.OnlyOnFaulted);

        Console.WriteLine(String.Format("Task {0} started", tasks[i].Id));
    }

    Console.ReadLine();
}

static void HandleException(Task task)
{
    Console.WriteLine(String.Format("Task {0} stopped", task.Id));

    // Check task status
    for (int i = 0; i < tasks.Count(); i++)
    {
        Console.WriteLine(String.Format("Task {0} status = {1}", i, tasks[i].Status));
    }
    // fFind and restart the task here
    if (tasks.Contains(task))
    {
        int index = Array.IndexOf(tasks, task);
        tasks[index] = Task.Run(() => { Thread.Sleep(1000); throw new Exception("BOOM"); })
         .ContinueWith(t => { HandleException(t); }
         , TaskContinuationOptions.OnlyOnFaulted);

        Console.WriteLine(String.Format("Task {0} started", tasks[index].Id));
    }
}

My application results in:

Task 3 started
Task 6 started
Task 5 stopped
Task 0 status = Running
Task 2 stopped
Task 1 status = Running
Task 0 status = Running
Task 1 status = Running

Since the task passed to the HandleException(t) is different from the original task, it is not found in the tasks[] and thus not restarted. Also looking at the states of the tasks[] it is not yet stopped. How can I properly restart my task?


Solution

  • That's because you store continuation task in your array, not original task (that is - you store result of ContinueWith). To fix, store original task instead:

    var task = Task.Run(() => { Thread.Sleep(1000); throw new Exception("BOOM");});
    task.ContinueWith(t => { HandleException(t); }
             , TaskContinuationOptions.OnlyOnFaulted);
    tasks[i] = task;