I play with cancelation token, and I would like to understand how this works. I have two async methods(in my example two but in theory I can have 100). I want to cancel work in all async methods if one of them throws an exception.
My idea is to cancel token in exception where all methods are called. When a token is canceled I would expect that other method stop working, but this is not happening.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace CancelationTest
{
class Program
{
static void Main(string[] args)
{
new Test();
Console.ReadKey();
}
}
public class Test
{
public Test()
{
Task.Run(() => MainAsync());
}
public static async Task MainAsync()
{
var cancellationTokenSource = new CancellationTokenSource();
try
{
var firstTask = FirstAsync(cancellationTokenSource.Token);
var secondTask = SecondAsync(cancellationTokenSource.Token);
Thread.Sleep(50);
Console.WriteLine("Begin");
await secondTask;
Console.WriteLine("hello");
await firstTask;
Console.WriteLine("world");
Console.ReadKey();
}
catch (OperationCanceledException e)
{
Console.WriteLine("Main OperationCanceledException cancel");
}
catch (Exception e)
{
Console.WriteLine("Main Exception + Cancel");
cancellationTokenSource.Cancel();
}
}
public static async Task FirstAsync(CancellationToken c)
{
c.ThrowIfCancellationRequested();
await Task.Delay(1000, c);
Console.WriteLine("Exception in first call");
throw new NotImplementedException("Exception in first call");
}
public static async Task SecondAsync(CancellationToken c)
{
c.ThrowIfCancellationRequested();
await Task.Delay(15000, c);
Console.WriteLine("SecondAsync is finished");
}
}
}
The second method finish work and delay task for 15 seconds even when the first method throws an exception.
What is result:
Begin
Exception in the first call
SecondAsync is finished
hello
Main Exception + Cancel
I would expect that secondAsync stop delay and throw OperationCancelException. I would expect this result:
Begin
Exception in first call
Main Exception + Cancel
Main OperationCanceledException cancel
Where am I making mistake? Why method SecondAsync is fully executed and doesn't throw an exception? And if I change the order of SecondAsync and FirstAsync than Second method stop to delay when the token is canceled and throw an exception.
Because the relevant part of your code is:
try
{
...
await secondTask;
await firstTask;
}
catch(...)
{
source.Cancel();
}
Now while the firstTask is started and has thrown, it is awaited after the secondTask. The exception won't surface in the caller until the task is awaited. And so the catch clause will only execute after secondTask has already completed. The Cancel() is just happening too late.
If you want your firstTask to interrupt the second one you will have to
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With