How it works
A task can finish successfully, fault, or be canceled. All three are terminal states, so IsCompleted does not mean success. The sample creates a task already completed through cancellation and prints true for IsCanceled, false for IsFaulted, and true for IsCompleted. Those facts are compatible rather than contradictory.
Awaiting a canceled task propagates an OperationCanceledException or a derived cancellation exception. The caught exception carries the token used to create this canceled task, which the final comparison confirms. A caller can use that association when deciding whether the cancellation belongs to an expected lifetime.
Task.FromCanceled requires a token whose cancellation has already been requested. It is not a way to manufacture an arbitrary task that will cancel later. A running implementation should observe an appropriate token cooperatively and finish according to its contract, rather than merely labeling an unfinished operation as canceled.
Do not report every completed task as a successful result or every cancellation as a defect. A user pressing Stop may produce an expected canceled outcome, while a fault indicates a different failure path. The interface can present those outcomes differently without erasing diagnostic information needed for an actual error.
Practice by replacing the canceled task with Task.FromResult(5) and Task.FromException<int>(new InvalidOperationException()). Build a small table of IsCompleted, IsCanceled, IsFaulted, and the behavior of await for each task. Keep the result access inside the appropriate success or await handling path.
Finally, combine canceled and successful tasks with WhenAll, then add a faulted task in a separate experiment. Observe the combined terminal state rather than inferring it from only one input. Reliable async reporting describes both the group outcome and any per-operation details the caller needs to decide whether partial work can be used.
A working example
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
var token = new CancellationToken(canceled: true);
Task<int> task = Task.FromCanceled<int>(token);
Console.WriteLine(task.IsCanceled);
Console.WriteLine(task.IsFaulted);
Console.WriteLine(task.IsCompleted);
try { await task; }
catch (OperationCanceledException error) { Console.WriteLine(error.CancellationToken == token); }
Expected output
True False True True
Completed includes successful, faulted, and canceled terminal states.