Search code examples
c#asp.net-corecancellation-tokencancellationtokensourcerequest-cancelling

Strange CancellationToken behaviour


Im testing CancellationToken behaviour in my UserRepository. When I use cancellationToken from parameters and cancel query with postman this works without exception (and it really cancels query). It also works when I create CancellationTokenSource and cancel it manually but then I have the exception:

System.Threading.Tasks.TaskCanceledException: A task was canceled.

No exception:

public async Task<List<UserDto>> GetAllUsers(CancellationToken cancellationToken)
    {   
        await Task.Delay(2000, cancellationToken);
    ...

Exception:

public async Task<List<UserDto>> GetAllUsers(CancellationToken cancellationToken)
    {
        CancellationTokenSource source = new CancellationTokenSource();
        CancellationToken token = source.Token;
        source.Cancel();
        
        await Task.Delay(2000, token);
    ...

Why are tokens handled differently?

UPDATED:

I HAVE an exception in first case but it is not shown in console for some reason. I can catch it:

public async Task<List<UserDto>> GetAllUsers(CancellationToken cancellationToken)
    {
        try
        {
            await Task.Delay(2000, cancellationToken);
        }
        catch (TaskCanceledException)
        {
            Console.WriteLine("exception");
        }
        ...

It is probably catched somewhere else. May be someone can explain this.


Solution

  • From the documentation, we can learn that If the cancellation token is signaled before the specified time delay, it will cause a TaskCanceledException exception and the task will be completed in the Canceled state. Therefore, when you manually call source.Cancel() inside the method, this will immediately mark the token as cancelled. When you call Task.Delay with this token, the task will detect that it has been cancelled and throw TaskCanceledException directly.

    When a client such as Postman cancels a request, the cancellation of the task simply stops the execution without causing an exception.