using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Threading ;
using System.Threading.Tasks ;
namespace ZeroLevel.Services.Async
{
/// <summary>
/// Helper methods for cancellation tokens.
/// </summary>
public static class CancellationTokenHelpers
{
/// <summary>
/// Initializes the static members.
/// </summary>
static CancellationTokenHelpers ( )
{
Canceled = new CancellationToken ( true ) ;
}
/// <summary>
/// Gets <see cref="CancellationToken.None"/>, a cancellation token that is never canceled.
/// </summary>
public static CancellationToken None { get { return CancellationToken . None ; } }
/// <summary>
/// Gets a cancellation token that is already canceled.
/// </summary>
public static CancellationToken Canceled { get ; private set ; }
/// <summary>
/// Creates a cancellation token that is canceled after the due time.
/// </summary>
/// <param name="dueTime">The due time after which to cancel the token.</param>
/// <returns>A cancellation token that is canceled after the due time.</returns>
public static NormalizedCancellationToken Timeout ( TimeSpan dueTime )
{
var cts = new CancellationTokenSource ( ) ;
cts . CancelAfter ( dueTime ) ;
return new NormalizedCancellationToken ( cts ) ;
}
/// <summary>
/// Creates a cancellation token that is canceled after the due time.
/// </summary>
/// <param name="dueTime">The due time after which to cancel the token.</param>
/// <returns>A cancellation token that is canceled after the due time.</returns>
public static NormalizedCancellationToken Timeout ( int dueTime )
{
var cts = new CancellationTokenSource ( ) ;
cts . CancelAfter ( dueTime ) ;
return new NormalizedCancellationToken ( cts ) ;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="cancellationTokens">The cancellation tokens to reduce.</param>
public static NormalizedCancellationToken Normalize ( params CancellationToken [ ] cancellationTokens )
{
return Normalize ( ( IEnumerable < CancellationToken > ) cancellationTokens ) ;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="cancellationTokens">The cancellation tokens to reduce.</param>
public static NormalizedCancellationToken Normalize ( IEnumerable < CancellationToken > 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 ) ) ;
}
/// <summary>
/// Creates a cancellation token that is canceled when the provided <see cref="Task"/> completes.
/// </summary>
/// <param name="source">The task to observe.</param>
/// <param name="continuationOptions">The options to use for the task continuation.</param>
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 ) ;
}
/// <summary>
/// Creates a cancellation token that is canceled when the provided <see cref="Task"/> completes.
/// </summary>
/// <param name="source">The task to observe.</param>
public static NormalizedCancellationToken FromTask ( Task source )
{
return FromTask ( source , TaskContinuationOptions . None ) ;
}
}
}