Retry a task multiple times based on user input in case of an exception in task

后端 未结 3 1701
甜味超标
甜味超标 2020-11-27 05:29

All the service calls in my application are implemented as tasks.When ever a task is faulted ,I need to present the user with a dialog box to retry the last operation failed

3条回答
  •  生来不讨喜
    2020-11-27 06:15

    When at the high level, I find it helps to make a function signature from what you have and what you want.

    You have:

    • A function that gives you a task (Func). We'll use the function because tasks themselves are not retryable in general.
    • A function that determines if the overall task is completed or should be retried (Func)

    You want:

    • An overall Task

    So you'll have a function like:

    Task Retry(Func action, Func shouldRetry);
    

    Extending the practice inside the function, tasks pretty much have 2 operations to do with them, read their state and ContinueWith. To make your own tasks, TaskCompletionSource is a good starting point. A first try might look something like:

    //error checking
    var result = new TaskCompletionSource();
    action().ContinueWith((t) => 
      {
        if (shouldRetry(t))
            action();
        else
        {
            if (t.IsFaulted)
                result.TrySetException(t.Exception);
            //and similar for Canceled and RunToCompletion
        }
      });
    
    
    

    The obvious problem here is that only 1 retry will ever happen. To get around that, you need to make a way for the function to call itself. The usual way to do this with lambdas is something like this:

    //error checking
    var result = new TaskCompletionSource();
    
    Func retryRec = null; //declare, then assign
    retryRec = (t) => { if (shouldRetry(t))
                            return action().ContinueWith(retryRec).Unwrap();
                        else
                        {
                            if (t.IsFaulted) 
                                result.TrySetException(t.Exception);
                            //and so on
                            return result.Task; //need to return something
                         }
                      };
     action().ContinueWith(retryRec);
     return result.Task;
    
        

    提交回复
    热议问题