using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace ZeroLevel.Services.Async { /// /// Helper methods for cancellation tokens. /// public static class CancellationTokenHelpers { /// /// Initializes the static members. /// static CancellationTokenHelpers() { Canceled = new CancellationToken(true); } /// /// Gets , a cancellation token that is never canceled. /// public static CancellationToken None { get { return CancellationToken.None; } } /// /// Gets a cancellation token that is already canceled. /// public static CancellationToken Canceled { get; private set; } /// /// Creates a cancellation token that is canceled after the due time. /// /// The due time after which to cancel the token. /// A cancellation token that is canceled after the due time. public static NormalizedCancellationToken Timeout(TimeSpan dueTime) { var cts = new CancellationTokenSource(); cts.CancelAfter(dueTime); return new NormalizedCancellationToken(cts); } /// /// Creates a cancellation token that is canceled after the due time. /// /// The due time after which to cancel the token. /// A cancellation token that is canceled after the due time. public static NormalizedCancellationToken Timeout(int dueTime) { var cts = new CancellationTokenSource(); cts.CancelAfter(dueTime); return new NormalizedCancellationToken(cts); } /// /// Reduces a set of cancellation tokens by removing any cancellation tokens that cannot be canceled. If any tokens are already canceled, the returned token will be canceled. /// /// The cancellation tokens to reduce. public static NormalizedCancellationToken Normalize(params CancellationToken[] cancellationTokens) { return Normalize((IEnumerable)cancellationTokens); } /// /// Reduces a set of cancellation tokens by removing any cancellation tokens that cannot be canceled. If any tokens are already canceled, the returned token will be canceled. /// /// The cancellation tokens to reduce. public static NormalizedCancellationToken Normalize(IEnumerable cancellationTokens) { var tokens = cancellationTokens.Where(t => t.CanBeCanceled).ToArray(); if (tokens.Length == 0) return new NormalizedCancellationToken(); if (tokens.Length == 1) return new NormalizedCancellationToken(tokens[0]); var alreadyCanceled = tokens.FirstOrDefault(t => t.IsCancellationRequested); if (alreadyCanceled.IsCancellationRequested) return new NormalizedCancellationToken(alreadyCanceled); return new NormalizedCancellationToken(CancellationTokenSource.CreateLinkedTokenSource(tokens)); } /// /// Creates a cancellation token that is canceled when the provided completes. /// /// The task to observe. /// The options to use for the task continuation. public static NormalizedCancellationToken FromTask(Task source, TaskContinuationOptions continuationOptions) { var cts = new CancellationTokenSource(); source.ContinueWith(_ => cts.Cancel(), CancellationToken.None, continuationOptions, TaskScheduler.Default); return new NormalizedCancellationToken(cts); } /// /// Creates a cancellation token that is canceled when the provided completes. /// /// The task to observe. public static NormalizedCancellationToken FromTask(Task source) { return FromTask(source, TaskContinuationOptions.None); } } }