/// <exception cref="System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
public void SetCanceled()
{
- if (!TrySetCanceled())
+ SetCanceled(default);
+ }
+
+ /// <summary>
+ /// Transitions the underlying
+ /// <see cref="System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>
+ /// state, and enables a token to be stored into the canceled
+ /// <see cref="System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <param name="cancellationToken">The cancellation token to bind to this <see
+ /// cref="System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <exception cref="System.InvalidOperationException">
+ /// The underlying <see cref="System.Threading.Tasks.Task{TResult}"/> is already in one
+ /// of the three final states:
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </exception>
+ /// <exception cref="System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
+ public void SetCanceled(CancellationToken cancellationToken)
+ {
+ if (!TrySetCanceled(cancellationToken))
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted);
}
}
public TaskCompletionSource(System.Threading.Tasks.TaskCreationOptions creationOptions) { }
public System.Threading.Tasks.Task<TResult> Task { get { throw null; } }
public void SetCanceled() { }
+ public void SetCanceled(System.Threading.CancellationToken cancellationToken) { }
public void SetException(System.Collections.Generic.IEnumerable<System.Exception> exceptions) { }
public void SetException(System.Exception exception) { }
public void SetResult(TResult result) { }
}
[Fact]
+ public static void RunTaskCompletionSourceTests_SetCanceled()
+ {
+ CancellationTokenSource cts = new CancellationTokenSource();
+ TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
+
+ tcs.SetCanceled(cts.Token);
+
+ Assert.Equal(TaskStatus.Canceled, tcs.Task.Status);
+
+ var ae = Assert.Throws<AggregateException>(() => tcs.Task.Result);
+ var tce = Assert.IsType<TaskCanceledException>(ae.InnerException);
+ Assert.Equal(cts.Token, tce.CancellationToken);
+
+ // Try to cancel again
+ Assert.Throws<InvalidOperationException>(() => tcs.SetCanceled(cts.Token));
+ }
+
+ [Fact]
public static void RunTaskCompletionSourceTests_CancellationTests()
{
// Test that cancellation is persistent
innerTcs.SetException(new InvalidOperationException());
break;
case TaskStatus.Canceled:
- innerTcs.TrySetCanceled(CreateCanceledToken());
+ innerTcs.SetCanceled(CreateCanceledToken());
break;
}
innerTcs.SetException(new InvalidOperationException());
break;
case TaskStatus.Canceled:
- innerTcs.TrySetCanceled(CreateCanceledToken());
+ innerTcs.SetCanceled(CreateCanceledToken());
break;
}
outerTcs.SetResult(null);
break;
case TaskStatus.Canceled:
- outerTcs.TrySetCanceled(CreateCanceledToken());
+ outerTcs.SetCanceled(CreateCanceledToken());
break;
case TaskStatus.Faulted:
outerTcs.SetException(new InvalidCastException());
outerTcs.SetResult(null); // cancellation
break;
case TaskStatus.Canceled:
- outerTcs.TrySetCanceled(CreateCanceledToken());
+ outerTcs.SetCanceled(CreateCanceledToken());
break;
case TaskStatus.Faulted:
outerTcs.SetException(new InvalidCastException());