I was experimenting different ways of cancellations. Here you'll see 5 different approaches and there is no doubt about the first four approaches. (These are commented but kept to avoid discussion on them). I'd like to know about the last approach(approach-5 shown below):
using static System.Console;
WriteLine("Simple cancellation demonstration.");
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
// This token is used for a follow-up question
var token2 = tokenSource.Token;
var printTask = Task.Run
(
() =>
{
// A loop that runs 100 times
for (int i = 0; i < 100; i++)
{
// Approach-1 :(Will cause RanToCompletion)
//if (token.IsCancellationRequested)
//{
// WriteLine("Cancelling the print activity.");
// // Do some cleanups, if required
// return;
//}
//// Approach-2
//if (token.IsCancellationRequested)
//{
// WriteLine("Cancelling the print activity.");
// // Do some cleanups, if required
// throw new OperationCanceledException(token);
//}
// Approach-3
// token.ThrowIfCancellationRequested();
//// Approach 4
//if (token.IsCancellationRequested)
//{
// // Do some cleanups, if required
// token.ThrowIfCancellationRequested();
//}
// Approach 5
if (token.IsCancellationRequested)
{
WriteLine("Cancelling the print activity.");
throw new OperationCanceledException("Raised a cancellation request"); // Causing Faulted state
// throw new OperationCanceledException(); // Causing Faulted state also
}
WriteLine($"{i}");
// Imposing the sleep to make some delay
Thread.Sleep(500);
}
}, token
);
WriteLine("Enter c to cancel the task.");
char ch = ReadKey().KeyChar;
if (ch.Equals('c'))
{
WriteLine("\nTask cancellation requested.");
tokenSource.Cancel();
}
// Wait till the task finishes the execution[ Not for production code]
while (!printTask.IsCompleted) { }
WriteLine($"The final status of printTask is: {printTask.Status}");
WriteLine("End of the main thread.");
Here is a sample output:
Simple cancellation demonstration.
Enter c to cancel the task.
0
1
2
c
Task cancellation requested.
Cancelling the print activity.
The final status of printTask is: Faulted
End of the main thread.
So, I can see when I do not pass the token as a parameter (inside the exception), the state is Faulted,but not canceled. Now I have the following question:
Is this an expected behavior?
Additional note: I have seen the online link:https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-cancellation states:
If the token's IsCancellationRequested property returns false or if the exception's token doesn't match the Task's token, the OperationCanceledException is treated like a normal exception, causing the Task to transition to the Faulted state.
But this does not clear the doubt yet.Please let me know what are the basics that I am missing here?
Should I conclude that raising an OperationCanceledException without the token will always cause a Faulted state?
It's because
tokenandtoken2are the same token.