private static Task <TOuterResult> ThenImpl <TTask, TOuterResult>(this TTask task, Func <TTask, Task <TOuterResult> > continuation, CancellationToken cancellationToken, bool runSynchronously) where TTask : Task { // Stay on the same thread if we can if (task.IsCompleted) { if (task.IsFaulted) { return(TaskHelpers.FromErrors <TOuterResult>(task.Exception.InnerExceptions)); } if (task.IsCanceled || cancellationToken.IsCancellationRequested) { return(TaskHelpers.Canceled <TOuterResult>()); } if (task.Status == TaskStatus.RanToCompletion) { try { return(continuation(task)); } catch (Exception ex) { return(TaskHelpers.FromError <TOuterResult>(ex)); } } } // Split into a continuation method so that we don't create a closure unnecessarily return(ThenImplContinuation(task, continuation, cancellationToken, runSynchronously)); }
private static IEnumerable <Task <object> > CanceledTaskEnumerable_Generic(List <string> log) { log.Add("first"); yield return(TaskHelpers.Canceled <object>()); log.Add("second"); }
/// <summary> /// Changes the return value of a task to the given result, if the task ends in the RanToCompletion state. /// This potentially imposes an extra ContinueWith to convert a non-completed task, so use this with caution. /// </summary> internal static Task <TResult> ToTask <TResult>(this Task task, CancellationToken cancellationToken = default(CancellationToken), TResult result = default(TResult)) { if (task == null) { return(null); } // Stay on the same thread if we can if (task.IsCompleted) { if (task.IsFaulted) { return(TaskHelpers.FromErrors <TResult>(task.Exception.InnerExceptions)); } if (task.IsCanceled || cancellationToken.IsCancellationRequested) { return(TaskHelpers.Canceled <TResult>()); } if (task.Status == TaskStatus.RanToCompletion) { return(TaskHelpers.FromResult(result)); } } // Split into a continuation method so that we don't create a closure unnecessarily return(ToTaskContinuation(task, result)); }
public void Canceled_Generic_ReturnsCanceledTask() { Task <string> result = TaskHelpers.Canceled <string>(); Assert.NotNull(result); Assert.True(result.IsCanceled); }
private static IEnumerable <Task> CanceledTaskEnumerable(List <string> log) { log.Add("first"); yield return(TaskHelpers.Canceled()); log.Add("second"); }
public void Canceled_ReturnsCanceledTask() { Task result = TaskHelpers.Canceled(); Assert.NotNull(result); Assert.True(result.IsCanceled); }
public static Task IterateImpl(IEnumerator <Task> enumerator, CancellationToken cancellationToken) { try { while (true) { if (cancellationToken.IsCancellationRequested) { return(TaskHelpers.Canceled()); } if (!enumerator.MoveNext()) { return(TaskHelpers.Completed()); } var currentTask = enumerator.Current; if (currentTask.Status == TaskStatus.RanToCompletion) { continue; } if (currentTask.IsCanceled || currentTask.IsFaulted) { return(currentTask); } return(IterateImplIncompleteTask(enumerator, currentTask, cancellationToken)); } } catch (Exception ex) { return(TaskHelpers.FromError(ex)); } }
public void TrySetFromTask_IfSourceTaskIsCanceled_CancelsTaskCompletionSource() { TaskCompletionSource <string> tcs = new TaskCompletionSource <string>(); Task canceledTask = TaskHelpers.Canceled <object>(); tcs.TrySetFromTask(canceledTask); Assert.Equal(TaskStatus.Canceled, tcs.Task.Status); }
public async Task ConvertFromCancelledTaskShouldBeHandled() { // Arrange var task = TaskHelpers.Canceled().CastToObject(); // Act & Assert await Assert.ThrowsAsync <TaskCanceledException>(() => task); Assert.Equal(TaskStatus.Canceled, task.Status); }
internal static Task <TOuterResult> CastFromobject <TOuterResult>(this Task <object> task) { // Stay on the same thread if we can if (task.IsCompleted) { if (task.IsFaulted) { return(TaskHelpers.FromErrors <TOuterResult>(task.Exception.InnerExceptions)); } if (task.IsCanceled) { return(TaskHelpers.Canceled <TOuterResult>()); } if (task.Status == TaskStatus.RanToCompletion) { try { return(TaskHelpers.FromResult <TOuterResult>((TOuterResult)task.Result)); } catch (Exception exception) { return(TaskHelpers.FromError <TOuterResult>(exception)); } } } TaskCompletionSource <TOuterResult> tcs = new TaskCompletionSource <TOuterResult>(); // schedule a synchronous task to cast: no need to worry about sync context or try/catch task.ContinueWith(innerTask => { if (innerTask.IsFaulted) { tcs.SetException(innerTask.Exception.InnerExceptions); } else if (innerTask.IsCanceled) { tcs.SetCanceled(); } else { try { tcs.SetResult((TOuterResult)innerTask.Result); } catch (Exception exception) { tcs.SetException(exception); } } }, TaskContinuationOptions.ExecuteSynchronously); return(tcs.Task); }
public void TryGetResult_CanceledTask_ReturnsFalse() { // Arrange var task = TaskHelpers.Canceled <int>(); // Act int value; bool result = task.TryGetResult(out value); // Assert Assert.False(result); }
public static Task <TOuterResult> CastFromObject <TOuterResult>(this Task <object> task) { if (task.IsCompleted) { if (task.IsFaulted) { return(TaskHelpers.FromErrors <TOuterResult>(task.Exception.InnerExceptions)); } if (task.IsCanceled) { return(TaskHelpers.Canceled <TOuterResult>()); } if (task.Status == TaskStatus.RanToCompletion) { try { return(TaskHelpers.FromResult((TOuterResult)task.Result)); } catch (Exception exception) { return(TaskHelpers.FromError <TOuterResult>(exception)); } } } var tcs = new TaskCompletionSource <TOuterResult>(); task.ContinueWith(innerTask => { if (innerTask.IsFaulted) { tcs.SetException(innerTask.Exception.InnerExceptions); } else if (innerTask.IsCanceled) { tcs.SetCanceled(); } else { try { tcs.SetResult((TOuterResult)innerTask.Result); } catch (Exception exception) { tcs.SetException(exception); } } }, TaskContinuationOptions.ExecuteSynchronously); return(tcs.Task); }
public CatchResult Throw() { if (base.Task.IsFaulted || base.Task.IsCanceled) { return(new CatchResult { Task = base.Task }); } // Canceled via CancelationToken return(new CatchResult { Task = TaskHelpers.Canceled() }); }
public Task ConvertFromCancelledTaskOfStringShouldBeHandled() { // Arrange return(TaskHelpers.Canceled <string>() // Act .CastToObject() // Assert .ContinueWith((task) => { Assert.Equal(TaskStatus.Canceled, task.Status); })); }
private static Task IterateImpl(IEnumerator <Task> enumerator, CancellationToken cancellationToken, Func <Task, bool> breakCondition) { try { while (true) { // short-circuit: iteration canceled if (cancellationToken.IsCancellationRequested) { return(TaskHelpers.Canceled()); } // short-circuit: iteration complete if (!enumerator.MoveNext()) { return(TaskHelpers.Completed()); } // fast case: Task completed synchronously & successfully Task currentTask = enumerator.Current; if (currentTask.Status == TaskStatus.RanToCompletion) { if (breakCondition != null && breakCondition(currentTask)) { return(currentTask); } continue; } // fast case: Task completed synchronously & unsuccessfully if (currentTask.IsCanceled || currentTask.IsFaulted) { return(currentTask); } // slow case: Task isn't yet complete return(IterateImplIncompleteTask(enumerator, currentTask, cancellationToken, breakCondition)); } } catch (Exception ex) { return(TaskHelpers.FromError(ex)); } }
private static Task <TResult> CatchImpl <TResult>(this Task task, Func <Task <TResult> > continuation, CancellationToken cancellationToken) { // Stay on the same thread if we can if (task.IsCompleted) { if (task.IsFaulted) { try { Task <TResult> resultTask = continuation(); if (resultTask == null) { // Not a resource because this is an internal class, and this is a guard clause that's intended // to be thrown by us to us, never escaping out to end users. throw new InvalidOperationException("You must set the Task property of the CatchInfo returned from the TaskHelpersExtensions.Catch continuation."); } return(resultTask); } catch (Exception ex) { return(TaskHelpers.FromError <TResult>(ex)); } } if (task.IsCanceled || cancellationToken.IsCancellationRequested) { return(TaskHelpers.Canceled <TResult>()); } if (task.Status == TaskStatus.RanToCompletion) { TaskCompletionSource <TResult> tcs = new TaskCompletionSource <TResult>(); tcs.TrySetFromTask(task); return(tcs.Task); } } // Split into a continuation method so that we don't create a closure unnecessarily return(CatchImplContinuation(task, continuation)); }
private static Task <TOuterResult> ThenImplContinuation <TOuterResult, TTask>(TTask task, Func <TTask, Task <TOuterResult> > continuation, CancellationToken cancellationToken) where TTask : Task { SynchronizationContext syncContext = SynchronizationContext.Current; return(task.ContinueWith(innerTask => { if (innerTask.IsFaulted) { return TaskHelpers.FromErrors <TOuterResult>(innerTask.Exception.InnerExceptions); } if (innerTask.IsCanceled || cancellationToken.IsCancellationRequested) { return TaskHelpers.Canceled <TOuterResult>(); } TaskCompletionSource <Task <TOuterResult> > tcs = new TaskCompletionSource <Task <TOuterResult> >(); if (syncContext != null) { syncContext.Post(state => { try { tcs.TrySetResult(continuation(task)); } catch (Exception ex) { tcs.TrySetException(ex); } }, state: null); } else { tcs.TrySetResult(continuation(task)); } return tcs.Task.FastUnwrap(); }).FastUnwrap()); }
public static Task <object> CastToObject(this Task task) { if (task.IsCompleted) { if (task.IsFaulted) { return(TaskHelpers.FromErrors <object>(task.Exception.InnerExceptions)); } if (task.IsCanceled) { return(TaskHelpers.Canceled <object>()); } if (task.Status == TaskStatus.RanToCompletion) { return(TaskHelpers.FromResult((object)null)); } } var tcs = new TaskCompletionSource <object>(); task.ContinueWith(innerTask => { if (innerTask.IsFaulted) { tcs.SetException(innerTask.Exception.InnerExceptions); } else if (innerTask.IsCanceled) { tcs.SetCanceled(); } else { tcs.SetResult(null); } }, TaskContinuationOptions.ExecuteSynchronously); return(tcs.Task); }