Last active
September 11, 2024 04:58
-
-
Save Rmanaf/4012c30a206029951bd42cbc542487fb to your computer and use it in GitHub Desktop.
A collection of extension methods for the Task class
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
/// <summary> | |
/// A collection of extension methods for the Task class | |
/// </summary> | |
public static class TaskExtensions | |
{ | |
/// <summary> | |
/// Introduces a delay before continuing with the next task. | |
/// This method is used for non-generic tasks (Task without a result). | |
/// </summary> | |
/// <param name="task">The task to delay after.</param> | |
/// <param name="milliseconds">The amount of time to delay in milliseconds.</param> | |
/// <param name="continueOnCapturedContext"> | |
/// If true, the continuation will run on the captured synchronization context (e.g., UI thread if applicable). | |
/// </param> | |
/// <returns>A new task that will complete after the delay.</returns> | |
public static Task Delay(this Task task, int milliseconds, bool continueOnCapturedContext = true) | |
{ | |
return task.ContinueWith(async t => | |
{ | |
await Task.Delay(milliseconds); | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default).Unwrap(); | |
} | |
/// <summary> | |
/// Introduces a delay before continuing with the next task. | |
/// This method is used for non-generic tasks (Task without a result). | |
/// </summary> | |
/// <param name="task">The task to delay after.</param> | |
/// <param name="timeSpan">The amount of time to delay as a TimeSpan.</param> | |
/// <param name="continueOnCapturedContext"> | |
/// If true, the continuation will run on the captured synchronization context (e.g., UI thread if applicable). | |
/// </param> | |
/// <returns>A new task that will complete after the delay.</returns> | |
public static Task Delay(this Task task, TimeSpan timeSpan, bool continueOnCapturedContext = true) | |
{ | |
return task.ContinueWith(async t => | |
{ | |
await Task.Delay(timeSpan); | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default).Unwrap(); | |
} | |
/// <summary> | |
/// Introduces a delay before continuing with the next task. | |
/// This method is used for tasks that return a result (Task<T>). | |
/// The result of the previous task is passed forward after the delay. | |
/// </summary> | |
/// <typeparam name="T">The type of the result produced by the task.</typeparam> | |
/// <param name="task">The task to delay after.</param> | |
/// <param name="milliseconds">The amount of time to delay in milliseconds.</param> | |
/// <param name="continueOnCapturedContext"> | |
/// If true, the continuation will run on the captured synchronization context (e.g., UI thread if applicable). | |
/// </param> | |
/// <returns>A new task that will complete after the delay and will pass forward the result of the previous task.</returns> | |
public static Task<T> Delay<T>(this Task<T> task, int milliseconds, bool continueOnCapturedContext = true) | |
{ | |
return task.ContinueWith(async t => | |
{ | |
var result = t.Result; // Capture the result of the task | |
await Task.Delay(milliseconds); // Delay for the specified time | |
return result; // Return the result after the delay | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default).Unwrap(); | |
} | |
/// <summary> | |
/// Introduces a delay before continuing with the next task. | |
/// This method is used for tasks that return a result (Task<T>). | |
/// The result of the previous task is passed forward after the delay. | |
/// </summary> | |
/// <typeparam name="T">The type of the result produced by the task.</typeparam> | |
/// <param name="task">The task to delay after.</param> | |
/// <param name="timeSpan">The amount of time to delay as a TimeSpan.</param> | |
/// <param name="continueOnCapturedContext"> | |
/// If true, the continuation will run on the captured synchronization context (e.g., UI thread if applicable). | |
/// </param> | |
/// <returns>A new task that will complete after the delay and will pass forward the result of the previous task.</returns> | |
public static Task<T> Delay<T>(this Task<T> task, TimeSpan timeSpan, bool continueOnCapturedContext = true) | |
{ | |
return task.ContinueWith(async t => | |
{ | |
var result = t.Result; // Capture the result of the task | |
await Task.Delay(timeSpan); // Delay for the specified TimeSpan | |
return result; // Return the result after the delay | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default).Unwrap(); | |
} | |
/// <summary> | |
/// Executes the given action if the task completes successfully. | |
/// </summary> | |
/// <param name="task">The task to chain the success handler to.</param> | |
/// <param name="onSuccess">The action to execute on task success.</param> | |
/// <param name="continueOnCapturedContext">Whether to continue on the captured context (typically UI thread).</param> | |
/// <returns>A task that will execute the success action if the original task completes successfully.</returns> | |
public static Task Then(this Task task, Action onSuccess, bool continueOnCapturedContext = true) | |
{ | |
task.ContinueWith(t => | |
{ | |
if (t.IsCompletedSuccessfully) | |
{ | |
onSuccess(); | |
} | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default); | |
return task; | |
} | |
/// <summary> | |
/// Executes the given action with the result if the task completes successfully. | |
/// </summary> | |
/// <typeparam name="T">The type of the result of the task.</typeparam> | |
/// <param name="task">The task to chain the success handler to.</param> | |
/// <param name="onSuccess">The action to execute with the result on task success.</param> | |
/// <param name="continueOnCapturedContext">Whether to continue on the captured context (typically UI thread).</param> | |
/// <returns>A task that will execute the success action with the result if the original task completes successfully.</returns> | |
public static Task Then<T>(this Task<T> task, Action<T> onSuccess, bool continueOnCapturedContext = true) | |
{ | |
task.ContinueWith(t => | |
{ | |
if (t.IsCompletedSuccessfully) | |
{ | |
onSuccess(t.Result); | |
} | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default); | |
return task; | |
} | |
/// <summary> | |
/// Asynchronously executes the given function if the task completes successfully. | |
/// </summary> | |
/// <param name="task">The task to chain the async success handler to.</param> | |
/// <param name="onSuccessAsync">The async function to execute on task success.</param> | |
/// <param name="continueOnCapturedContext">Whether to continue on the captured context (typically UI thread).</param> | |
/// <returns>A task that will execute the async success function if the original task completes successfully.</returns> | |
public static Task Then(this Task task, Func<Task> onSuccessAsync, bool continueOnCapturedContext = true) | |
{ | |
task.ContinueWith(async t => | |
{ | |
if (t.IsCompletedSuccessfully) | |
{ | |
await onSuccessAsync(); | |
} | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default).Unwrap(); | |
return task; | |
} | |
/// <summary> | |
/// Asynchronously executes the given function with the result if the task completes successfully. | |
/// </summary> | |
/// <typeparam name="T">The type of the result of the task.</typeparam> | |
/// <param name="task">The task to chain the async success handler to.</param> | |
/// <param name="onSuccessAsync">The async function to execute with the result on task success.</param> | |
/// <param name="continueOnCapturedContext">Whether to continue on the captured context (typically UI thread).</param> | |
/// <returns>A task that will execute the async success function with the result if the original task completes successfully.</returns> | |
public static Task Then<T>(this Task<T> task, Func<T, Task> onSuccessAsync, bool continueOnCapturedContext = true) | |
{ | |
task.ContinueWith(async t => | |
{ | |
if (t.IsCompletedSuccessfully) | |
{ | |
await onSuccessAsync(t.Result); | |
} | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default).Unwrap(); | |
return task; | |
} | |
/// <summary> | |
/// Executes the given action if the task encounters an error. | |
/// </summary> | |
/// <param name="task">The task to chain the error handler to.</param> | |
/// <param name="onError">The action to execute on task failure.</param> | |
/// <param name="continueOnCapturedContext">Whether to continue on the captured context (typically UI thread).</param> | |
/// <returns>A task that will execute the error action if the original task fails.</returns> | |
public static Task Catch(this Task task, Action<Exception> onError, bool continueOnCapturedContext = true) | |
{ | |
task.ContinueWith(t => | |
{ | |
if (t.IsFaulted && t.Exception != null) | |
{ | |
onError(t.Exception.InnerException ?? t.Exception); | |
} | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default); | |
return task; | |
} | |
/// <summary> | |
/// Asynchronously executes the given function if the task encounters an error. | |
/// </summary> | |
/// <param name="task">The task to chain the async error handler to.</param> | |
/// <param name="onErrorAsync">The async function to execute on task failure.</param> | |
/// <param name="continueOnCapturedContext">Whether to continue on the captured context (typically UI thread).</param> | |
/// <returns>A task that will execute the async error function if the original task fails.</returns> | |
public static Task Catch(this Task task, Func<Exception, Task> onErrorAsync, bool continueOnCapturedContext = true) | |
{ | |
task.ContinueWith(async t => | |
{ | |
if (t.IsFaulted && t.Exception != null) | |
{ | |
await onErrorAsync(t.Exception.InnerException ?? t.Exception); // Handle task failure asynchronously | |
} | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default).Unwrap(); | |
return task; | |
} | |
/// <summary> | |
/// Executes the given action after the task completes, regardless of success or failure. | |
/// </summary> | |
/// <param name="task">The task to chain the final action to.</param> | |
/// <param name="onFinally">The action to execute after task completion.</param> | |
/// <param name="continueOnCapturedContext">Whether to continue on the captured context (typically UI thread).</param> | |
/// <returns>A task that will execute the final action after the original task completes.</returns> | |
public static Task Finally(this Task task, Action onFinally, bool continueOnCapturedContext = true) | |
{ | |
task.ContinueWith(t => | |
{ | |
onFinally(); | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default); | |
return task; | |
} | |
/// <summary> | |
/// Asynchronously executes the given function after the task completes, regardless of success or failure. | |
/// </summary> | |
/// <param name="task">The task to chain the final async function to.</param> | |
/// <param name="onFinallyAsync">The async function to execute after task completion.</param> | |
/// <param name="continueOnCapturedContext">Whether to continue on the captured context (typically UI thread).</param> | |
/// <returns>A task that will execute the final async function after the original task completes.</returns> | |
public static Task Finally(this Task task, Func<Task> onFinallyAsync, bool continueOnCapturedContext = true) | |
{ | |
task.ContinueWith(async t => | |
{ | |
await onFinallyAsync(); | |
}, continueOnCapturedContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default).Unwrap(); | |
return task; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage