using System; using System.Threading; using System.Threading.Tasks; // ReSharper disable MemberCanBePrivate.Global namespace Nullframes.Threading.Tasks { /// /// Class contains extension methods for Tasks /// public static class TaskExtensions { #region --- Timeout --- /// /// Set a timout for the completion of the target . A /// is thrown if the target task does not complete within the set timeframe. /// public static async void Timeout(this Task mightTimeout, int timeoutMillisecond, CancellationToken ct = default) { await Task.WhenAny(mightTimeout, TimeoutInternalTaskAsync(timeoutMillisecond, ct)); } /// /// Set a timout for the completion of the target . A /// is thrown if the target task does not complete within the set timeframe. /// public static async void Timeout(this Task mightTimeout, TimeSpan timeoutTimeSpan, CancellationToken ct = default) { await TimeoutAsync(mightTimeout, timeoutTimeSpan.Milliseconds, ct); } //-------------------------------------------------------------------------------------------------------------- /// /// Set a timout for the completion of the target . A /// is thrown if the target task does not complete within the set timeframe. /// private static async Task TimeoutInternalTaskAsync(int millisecondsTimeout, CancellationToken ct = default) { await Task.Delay(millisecondsTimeout, ct); throw new TimeoutException($"Timeout after {millisecondsTimeout}ms while awaiting a task!"); } #endregion #region --- Timeout Async --- /// /// Set a timout for the completion of the target . A /// is thrown if the target task does not complete within the set timeframe. /// public static Task TimeoutAsync(this Task mightTimeout, int timeoutMillisecond, CancellationToken ct = default) { return Task.WhenAny(mightTimeout, TimeoutInternalAsync(timeoutMillisecond, ct)); } /// /// Set a timout for the completion of the target . A /// is thrown if the target task does not complete within the set timeframe. /// public static Task TimeoutAsync(this Task mightTimeout, TimeSpan timeoutTimeSpan, CancellationToken ct = default) { return TimeoutAsync(mightTimeout, timeoutTimeSpan.Milliseconds, ct); } /// /// Set a timout for the completion of the target . A /// is thrown if the target task does not complete within the set timeframe. /// public static async Task TimeoutAsync(this Task mightTimeout, int timeoutMillisecond, CancellationToken ct = default) { return await await Task.WhenAny(mightTimeout, TimeoutInternalAsync(timeoutMillisecond, ct)); } /// /// Set a timout for the completion of the target . A /// is thrown if the target task does not complete within the set timeframe. /// public static async Task TimeoutAsync(this Task mightTimeout, TimeSpan timeoutTimeSpan, CancellationToken ct = default) { return await TimeoutAsync(mightTimeout, timeoutTimeSpan.Milliseconds, ct); } //-------------------------------------------------------------------------------------------------------------- private static async Task TimeoutInternalAsync(int millisecondsTimeout, CancellationToken ct = default) { await Task.Delay(millisecondsTimeout, ct); throw new TimeoutException($"Timeout after {millisecondsTimeout}ms while awaiting a task!"); } private static async Task TimeoutInternalAsync(int millisecondsTimeout, CancellationToken ct = default) { await Task.Delay(millisecondsTimeout, ct); throw new TimeoutException($"Timeout after {millisecondsTimeout}ms while awaiting a task!"); } #endregion //-------------------------------------------------------------------------------------------------------------- #region --- Generic Exception Handling --- /// /// Ignore any of type Exception that might occur during the execution of the /// target /// public static async Task IgnoreExceptionAsync(this Task task) where TException : Exception { try { await task; } catch (TException) { } } /// /// Ignore every that might occur during the execution of the /// target /// public static async Task IgnoreExceptionsAsync(this Task task) { try { await task; } catch (Exception) { // ignored } } /// /// Ignore any of type Exception that might occur during the execution of the /// target . You can set the default value returned by this /// if an exception occurs. /// public static async Task IgnoreExceptionAsync(this Task task, TResult defaultValue = default) where TException : Exception { try { return await task; } catch (TException) { } return defaultValue; } /// /// Ignore every that might occur during the execution of the /// target . You can set the default value returned by this /// if an exception occurs. /// public static async Task IgnoreExceptionsAsync(this Task task, TResult defaultValue = default) { try { return await task; } catch (Exception) { // ignored } return defaultValue; } #endregion #region --- Concrete Exception Handling --- /// /// Ignore any that might occur during the execution of the /// target /// public static async Task IgnoreTimeoutException(this Task task) => await IgnoreExceptionAsync(task); /// /// Ignore any that might occur during the execution of the /// target /// public static async Task IgnoreOperationCanceledException(this Task task) => await IgnoreExceptionAsync(task); /// /// Ignore any that might occur during the execution of the /// target /// public static async Task IgnoreThreadAbortException(this Task task) => await IgnoreExceptionAsync(task); #endregion #region --- Concrete Exception Handling Async --- /// /// Ignore any that might occur during the execution of the /// target . You can set the default value returned by this /// if an exception occurs. /// public static async Task IgnoreTimeoutExceptionAsync(this Task task, TResult defaultValue = default) => await IgnoreExceptionAsync(task, defaultValue); /// /// Ignore any that might occur during the execution of the /// target . You can set the default value returned by this /// if an exception occurs. /// public static async Task IgnoreOperationCanceledExceptionAsync(this Task task, TResult defaultValue = default) => await IgnoreExceptionAsync(task, defaultValue); /// /// Ignore any that might occur during the execution of the /// target . You can set the default value returned by this /// if an exception occurs. /// public static async Task IgnoreThreadAbortExceptionAsync(this Task task, TResult defaultValue = default) => await IgnoreExceptionAsync(task, defaultValue); #endregion } }