how cancel token work in these cases

rajesh yadav 291 Reputation points
2025-08-08T12:15:47.5066667+00:00

following code is from https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/cancel-an-async-task-or-a-list-of-tasks

i could not understand when it will show following two messages from last main code.

Console.WriteLine("Download task has been cancelled.");

Console.WriteLine("Download task completed before cancel request was processed.");
 Task finishedTask = await Task.WhenAny(new[] { cancelTask, sumPageSizesTask });
    if (finishedTask == cancelTask)
    {
        // wait for the cancellation to take place:
        try
        {
            await sumPageSizesTask;
            Console.WriteLine("Download task completed before cancel request was processed.");
        }
        catch (TaskCanceledException)
        {
            Console.WriteLine("Download task has been cancelled.");
        }
    }

    Console.WriteLine("Application ending.");
}

Developer technologies | ASP.NET | ASP.NET Core
0 comments No comments
{count} votes

Accepted answer
  1. Danny Nguyen (WICLOUD CORPORATION) 800 Reputation points Microsoft External Staff
    2025-08-11T10:33:00.0866667+00:00

    Hi @rajesh yadav , Since others have given great insights, I will offer what I've found regarding this subject.

    The two messages depend entirely on which task reaches a terminal state first and whether the cancellation token actually interrupts the download.

    • "Download task has been cancelled." You pressed Enter before all the downloads finished, and the cancellation token stopped the work mid-way. A download was still in progress when the cancel request hit, so sumPageSizesTask threw a TaskCanceledException and ended in the Canceled state.
    • "Download task completed before cancel request was processed." You pressed Enter before all the downloads finished, but they were so close to completion that the task finished normally before the cancellation token took effect. This case is rare, because most of the time the HTTP calls will observe the cancellation and throw before completing.

    Though through testing, I've found that sumPageSizesTask always complete before cancelTask, therefore finishedTask gets the value of sumPageSizesTask:

    Task finishedTask = await Task.WhenAny(new[] { cancelTask, sumPageSizesTask });
    

    Thus, this part is probably going to get skipped over:

    if (finishedTask == cancelTask)
    {
        // wait for the cancellation to take place:
        try
        {
            await sumPageSizesTask;
            Console.WriteLine("Download task completed before cancel request was processed.");
        }
        catch (TaskCanceledException)
        {
            Console.WriteLine("Download task has been cancelled.");
        }
    }
    

    You should also check out these documentations for more information on Task cancellation:CancellationTokenSource.Cancel Method (System.Threading) | Microsoft Learn

    Task Cancellation - .NET | Microsoft Learn

    Hope this clears things up


3 additional answers

Sort by: Most helpful
  1. AgaveJoe 30,206 Reputation points
    2025-08-08T15:10:48.74+00:00

    There are two tasks cancelTask and sumPageSizesTask. If the cancelTask finishes first then s_cts token is canceled s_cts.Cancel(); The if (finishedTask == cancelTask) is true and the try...catch block is executed. The HttpClient.GetAsync or ReadAsByteArrayAsync methods, which are passed the cancellation token, will detect the cancellation request and throw an OperationCanceledException. The catch block executes Console.WriteLine("Download task has been cancelled.");

    If sumPageSizesTask finishes first, then the if (finishedTask == cancelTask) is false and Console.WriteLine("Application ending."); is executed.

    The message "Download task completed before cancel request was processed." is only displayed if the cancelTask finishes first, but the sumPageSizesTask also finishes on its own before the await sumPageSizesTask; statement is executed. In this specific and rare case, the await on an already-completed task will succeed without throwing an exception, and the code will then print this message.

    You and 1 other person found this answer helpful.
    0 comments No comments

  2. SurferOnWww 4,811 Reputation points
    2025-08-09T02:39:52.9833333+00:00

    i could not understand when it will show following two messages from last main code.

    Console.WriteLine("Download task completed before cancel request was processed."); will never happen in any case. There is an exception as AgaveJoe stated in his answer. It is virtually impossible to print "Download task completed before cancel request was processed." with the sample code in the Microsoft document by manual operation. See my comment below If you want to test it.

    Console.WriteLine("Download task has been cancelled."); occurs only when the Enter key is pressed before completion of SumPageSizesAsync method.

    Why don't you use the debugger of Visual Studio? Put the break points as shown below and execute the application by clicking [Debug] => [Start Debugging]:

    enter image description here

    You found this answer helpful.

  3. Bruce (SqlWork.com) 79,101 Reputation points Volunteer Moderator
    2025-08-08T16:24:11.4033333+00:00

    setting cancel task does not immediately stop the task. during processing the code must check the value of the cancel token and exit. in the sample code, the test is in http request code.

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    
    var tokenSource = new CancellationTokenSource();
    var ct = tokenSource.Token;
    
    try
    {
        await Task.WhenAll(
    		Task.Run(() => 
    		{
    			for (var i = 0; i < 10; ++i)
    			{
    				// are we already canceled?
    				ct.ThrowIfCancellationRequested();
                    // do work
    				Thread.Sl eep(1000); // space required to save code
    			}
    		}),
    		Task.Run(() =>
    		{
    			// random reply between 1 and 11 seconds
    			var rnd = new Random();
    			var delay = rnd.Next(1, 11);
    
    			Thread.Sleep(delay * 1000); 
    			Console.WriteLine("Try canceling task...");
    			tokenSource.Cancel();
    		})
    	);
        Console.WriteLine("Completed");
    }
    catch (OperationCanceledException)
    {
       Console.WriteLine("task has been cancelled.");
    }
    
    

    notice the task checks for cancel before the work (sleep). if the cancel comes during the sleep and i < 9, then the next loop will throw the cancel error. but if the cancel is set when i == 9, then the work happens, and task completes before checking for the cancel.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.