Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the Task doesn't show canceled status

I am testing a simple console application created on Linqpad, idea is to have assured understanding of the working of Task and create a logic which works, when Task is completed, faulted or Canceled. I want to execute a logic only when Task is completed but not faulted or canceled.

void Main()
{
    CancellationTokenSource cts = new CancellationTokenSource(new TimeSpan(0,0,0,0,1000));

    Task t = Task.Run(() => Work(),cts.Token);
    try
    {
        t.Wait();
    }
    catch
    {
    }

    ("Completed :: " + t.IsCompleted).Dump();
    ("Canceled :: " + t.IsCanceled).Dump();
    ("Faulted :: " + t.IsFaulted).Dump();
}

public async Task Work()
{
    await Task.Delay(3000);
}

Following are the issues:

  1. I am able to confidently figure out the Completed and Faulted states, but even when in my view this code should lead to Task cancellation, the value of IsCanceled property is always false.

  2. Ideally when the Task is faulted, even though I am silently capturing the exception in a try catch block, it should show IsCompleted as false, but it always remain true, currently Linqpad doesn't have continue on error option, but I am assuming, it would turn false if I can continue on error

like image 219
Mrinal Kamboj Avatar asked Feb 03 '26 00:02

Mrinal Kamboj


1 Answers

I am able to confidently figure out the Completed and Faulted states, but even when in my view this code should lead to Task cancellation, the value of IsCanceled property is always false.

There is no automatism in cancellation. You are passing CancellationToken to Task.Run. If cancellation would occur while the task is starting, the start process would be interrupted by cancellation. Once the task is running, it is the task's method's responsibility to check the cancellation token. Wait is not doing that. It does not even know of the cancellation token. Hence, the task can never turn into the canceled state.

This is how you would observe cancellation:

void Main()
{
    CancellationTokenSource cts = new CancellationTokenSource(new TimeSpan(0,0,0,0,1000));

    Task t = Task.Run(() => Work(cts.Token),cts.Token);
    try
    {
        t.Wait();
    }
    catch
    {
    }

    ("Completed :: " + t.IsCompleted).Dump();
    ("Canceled :: " + t.IsCanceled).Dump();
    ("Faulted :: " + t.IsFaulted).Dump();
}

public async Task Work(CancellationToken token)
{
    await Task.Delay(3000, token);
}

Ideally when the Task is faulted, even though I am silently capturing the exception in a try catch block, it should show IsCompleted as false, but it always remain true

Check MSDN:

IsCompleted will return true when the task is in one of the three final states: RanToCompletion, Faulted, or Canceled.

like image 149
Sefe Avatar answered Feb 05 '26 13:02

Sefe