-
-
Save renestein/4353381 to your computer and use it in GitHub Desktop.
Aleš Roubíček
Task with retry logic.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace TaskWithRetry | |
{ | |
internal class Program | |
{ | |
private static void Main(string[] args) | |
{ | |
var task1 = Task<bool>.Factory.StartWithRetry(() => | |
{ | |
Console.WriteLine("running first task"); | |
throw new InvalidOperationException(); | |
return true; | |
}, 3); | |
bool isFirstCall = true; | |
var task2 = Task<bool>.Factory.StartWithRetry(() => | |
{ | |
Console.WriteLine("running second task"); | |
if (isFirstCall) | |
{ | |
isFirstCall = false; | |
throw new InvalidOperationException(); | |
} | |
return true; | |
}, 3); | |
try | |
{ | |
Console.WriteLine(task1.Result); | |
Console.WriteLine(task2.Result); | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine(e); | |
} | |
Console.ReadLine(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading.Tasks; | |
namespace TaskWithRetry | |
{ | |
public static class TaskFactoryExtensions | |
{ | |
public const int MIN_ATTEMPTS = 1; | |
public static Task<TResult> StartWithRetry<TResult>(this TaskFactory<TResult> taskFactory, Func<TResult> func, | |
int maxAttemps) | |
{ | |
if (taskFactory == null) | |
{ | |
throw new ArgumentNullException("taskFactory"); | |
} | |
if (func == null) | |
{ | |
throw new ArgumentNullException("func"); | |
} | |
if (maxAttemps < MIN_ATTEMPTS) | |
{ | |
throw new ArgumentException("maxAttemps"); | |
} | |
var tcs = new TaskCompletionSource<TResult>(); | |
int maxAttemptsOriginal = maxAttemps; | |
Action<Task> wrapperfunction = null; | |
wrapperfunction = previousTask => | |
{ | |
if (maxAttemptsOriginal == 0) | |
{ | |
//previousTask cannot be null! | |
tcs.TrySetException(previousTask.Exception); | |
return; | |
} | |
maxAttemptsOriginal--; | |
var task = taskFactory.StartNew(func); | |
task.ContinueWith(wrapperfunction, TaskContinuationOptions.OnlyOnFaulted); | |
task.ContinueWith(prevTask => | |
{ | |
if (prevTask.Status == TaskStatus.Canceled) | |
{ | |
tcs.TrySetCanceled(); | |
} | |
else | |
{ | |
tcs.TrySetResult(prevTask.Result); | |
} | |
}, | |
TaskContinuationOptions.NotOnFaulted | |
); | |
}; | |
wrapperfunction(null); | |
return tcs.Task; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ještě by bylo lepší lépe ošetřovat všechny výjimky, ošetřit lépe všechny stavy tasku., pracovat se SynchronizationContextem, zredukovat počet spouštěných tasků apod.