1

Am working with C#'s TaskFactory using ContinueWith function. The issue am trying to solve it this

  • Execute Foo().
  • If result succeeded, exit
  • If Foo() did not result in success, then iterate and execute Foo() until it results in success (max iterations 3)
  • If it doesn't succeed in 3 iterations, give up

The code I started with looks like this

var executeTask = Task.Factory.StartNew<ExecutionStatus>(() =>
        {
            return Foo();
        });
        executeTask.ContinueWith(task => CheckIfExecutionWasSuccessful(task)).
                        ContinueWith(task => CheckIfExecutionWasSuccessful(task)).
                        ContinueWith(task => CheckIfExecutionWasSuccessful(task)).
                        ContinueWith(task => CheckLastTimeBeforeGivingUp(task));

Foo() and CheckIfExecutionWasSuccessful() looks like this

ExecutionStatus Foo(){
      //Do my work
      return new ExecutionStatus(){Succeded = true}
     }

ExecutionStatus CheckIfExecutionWasSuccessful(Task<ExecutionStatus> task){
            if(task.Result.Succeeded) return task.Result;
            else return Foo()

Something tells me that this is not the best way to go about this problem. Any suggestions, ideas?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Karthik Balasubramanian
  • 1,127
  • 4
  • 13
  • 36
  • 2
    Are you using >=.net45? If so, you really should go `async/await` instead of using `.ContinueWith`. – spender Aug 19 '14 at 00:56
  • We are on .NET 4.0, I dont have the luxury to change it to 4.5. Am curious though, how would I go about this if am using async/await – Karthik Balasubramanian Aug 19 '14 at 01:03
  • 1
    You could just use a simple loop with async/await – jamesSampica Aug 19 '14 at 01:04
  • I could, but isn't this exactly the reason why we have Task.ContinueWith() ? I just need to figure out how I can conditionally invoke ContinueWith() without having to have a predicate inside CheckIfExecutionWasSuccessful() – Karthik Balasubramanian Aug 19 '14 at 01:12
  • Also it would be awesome if I can specify the number of iterations, instead of having to call ContinueWith() three times – Karthik Balasubramanian Aug 19 '14 at 01:13
  • 1
    Basically your issue is a solved problem using a two-year-old technology. Your code would be drastically simpler. – Kirk Woll Aug 19 '14 at 01:23
  • `Observable.Retry(Foo, 15).ToTask()` although `TaskFactory` in .net 4 is actually broken, (see `SynchronizationContext`). You could also think about using the async targeting pack. – Aron Aug 19 '14 at 01:24
  • 1
    Check [this](http://stackoverflow.com/a/21346870/1768303) and [this](http://stackoverflow.com/q/21324583/1768303). – noseratio Aug 19 '14 at 02:23

2 Answers2

3

I don't understand why are you making this more complicated by using multiple Tasks and ContinueWith(). Instead, write the code just like you would without Tasks and then run it in a Task:

Task.Factory.StartNew(() =>
{
    for (int i = 0; i < maxTries - 1; i++)
    {
        try
        {
            return Foo();
        }
        catch
        { }
    }

    return Foo();
});

This makes the code clearer, more obviously correct and easier to modify.

svick
  • 236,525
  • 50
  • 385
  • 514
0

Simple:

var MaxTries = 3;
var executeTask = Task.Factory.StartNew<ExecutionStatus>(() => Foo());

for(var i = 0; i < MaxTries; i++)
{
    executeTask = executeTask.ContinueWith(task => CheckIfExecutionWasSuccessful(task));
}

executeTask = executeTask.ContinueWith(task => CheckLastTimeBeforeGivingUp(task));
Radu Porumb
  • 785
  • 5
  • 7