When cancelling the following task, the task is not in state Canceled but Faulted:
private string ReturnString()
{
// throw new OperationCanceledException(_cancellationToken); // This puts task in faulted, not canceled
Task.Delay(5000, _cancellationToken).Wait(_cancellationToken); // Simulate work (with IO-bound call)
// throw new OperationCanceledException(_cancellationToken); // This puts task in faulted, not canceled
// _cancellationToken.ThrowIfCancellationRequested(); // This puts task in faulted, not canceled
// throw new Exception("Throwing this exception works!"); // This works as expected (faulted)
return "Ready";
}
private void SetReturnValueWithTaskContinuation()
{
SynchronizationContext synchronizationContext = SynchronizationContext.Current;
Task<string> task = Task.Run(() => ReturnString());
task.ContinueWith(
antecedent =>
{
if (antecedent.Status == TaskStatus.Canceled)
{
synchronizationContext.Post(result => _txtResultContinueWith.Text = (string)result, "Cancelled");
}
else if (antecedent.Status == TaskStatus.Faulted)
{
synchronizationContext.Post(result => _txtResultContinueWith.Text = (string)result, "Exception");
}
else
{
synchronizationContext.Post(result => _txtResultContinueWith.Text = (string)result, antecedent.Result);
}
});
}
I know, that the cancellation token has to be supplied when throwing an OperationCanceled Exception. I know, there are two ways of throwing an OperationCanceled Exception where the ThrowIfCancellationRequested() is the prefered one. And I know, that the cancellation token of the continuation chain should be different than the cancellation token of the task to cancel, otherwise the continuation chain will be canceled too. For the sake of simplification, I only use one cancellation token to cancel the task itself. But, the task has state "Faulted" and not "Canceled". Is that a bug? If not, than it is a usability issue of the TPL. Can somebody help?