Skip to content

Instantly share code, notes, and snippets.

@woloski
Created April 25, 2012 15:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save woloski/2490815 to your computer and use it in GitHub Desktop.
Save woloski/2490815 to your computer and use it in GitHub Desktop.
Fire and forget with TPL and retry on ASP.NET
Task.Factory.StartNew((state) =>
{
try
{
// use http://nuget.org/packages/TransientFaultHandling.Core
// the defaultfixed strategy retries 10 times every 1 second
RetryPolicy.DefaultFixed.ExecuteAction(() =>
{
// do something that might throw an exception like calling an http endpoint
});
}
catch
{
// if after the 10 retries keeps failing, swallow or log somewhere
}
}, new { RequestUrl = HttpContext.Request.Url } );
// since the HttpContext won't be available by the time the Task executes, send whatever you want (value types) through state as an anonymous object
// depends on: http://nuget.org/packages/TransientFaultHandling.Core and TPL
public static class FireAndForget
{
public static RetryPolicy DefaultRetryPolicy = RetryPolicy.DefaultFixed;
public static void ExecuteWithRetry(Action action)
{
ExecuteWithRetry(action, null, DefaultRetryPolicy);
}
public static void ExecuteWithRetry(Action action, RetryPolicy retryPolicy)
{
ExecuteWithRetry(action, null, retryPolicy);
}
public static void ExecuteWithRetry(Action<object> action, object state)
{
ExecuteWithRetry(action, state, DefaultRetryPolicy);
}
public static void ExecuteWithRetry(Action<object> action, object state, RetryPolicy retryPolicy)
{
ExecuteWithRetry(action, state, null, retryPolicy);
}
public static void ExecuteWithRetry(Action action, Action<Exception> onErrorAfterRetries)
{
ExecuteWithRetry(action, onErrorAfterRetries, DefaultRetryPolicy);
}
public static void ExecuteWithRetry(Action action, Action<Exception> onErrorAfterRetries, RetryPolicy retryPolicy)
{
Task.Factory.StartNew(() =>
{
try
{
retryPolicy.ExecuteAction(() =>
{
action();
});
}
catch (Exception ex)
{
if (onErrorAfterRetries != null)
onErrorAfterRetries(ex);
}
});
}
public static void ExecuteWithRetry(Action<object> action, object state, Action<Exception> onErrorAfterRetries)
{
ExecuteWithRetry(action, state, onErrorAfterRetries, DefaultRetryPolicy);
}
public static void ExecuteWithRetry(Action<object> action, object state, Action<Exception> onErrorAfterRetries, RetryPolicy retryPolicy)
{
Task.Factory.StartNew((taskState) =>
{
try
{
retryPolicy.ExecuteAction(() =>
{
action(taskState);
});
}
catch (Exception ex)
{
if (onErrorAfterRetries != null)
onErrorAfterRetries(ex);
}
}, state);
}
}
// simple fire and forget
FireAndForget.ExecuteWithRetry(() =>
{
// do something that takes a couple of seconds (like calling an http endpoint)
// create an artificial random exception
if (new Random(DateTime.Now.Second).Next(1, 2) == 1)
throw new Exception();
});
// passing state + handling error
FireAndForget.ExecuteWithRetry((state) =>
{
var url = ((dynamic)state).RequestUrl;
// do something that takes a couple of seconds (like calling an http endpoint)
// create an artificial random exception
if (new Random(DateTime.Now.Second).Next(1, 2) == 1)
throw new Exception();
},
state: new { RequestUrl = HttpContext.Request.Url },
onErrorAfterRetries: (exception) =>
{
// log somewhere
});
// you can override the retry policy by setting DefaultRetryPolicy or passing the parameter
@sballarati
Copy link

awesome! Thanks for sharing, it is very useful for us!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment