Перегрузка StartNew
, которую вы использовали, является источником бесконечной путаницы. Вдвойне, так как его тип на самом деле StartNew<Task<T>>
(вложенная задача), а не StartNew<T>
.
Токен сам по себе ничего не делает. Некоторый код где-то должен проверить токен и выдать исключение для выхода из Задачи.
Официальная документация следует этому шаблону:
var tokenSource = new CancellationTokenSource();
var ct = tokenSource.Token;
var task = Task.Run(() =>
{
while (...)
{
if (ct.IsCancellationRequested)
{
// cleanup your resources before throwing
ct.ThrowIfCancellationRequested();
}
}
}, ct); // Pass same token to Task.Run
Но если вы все равно проверяете токен и, возможно, выбрасываете исключение, зачем вам сначала передавать токен, и затем использовать такой же токен внутри замыкания?
Причина в том, что токен, который вы передаете, используется для того, чтобы перевести задачу в отмененное состояние.
Когда экземпляр задачи наблюдает исключение OperationCanceledException, генерируемое кодом пользователя, он сравнивает токен исключения со связанным с ним токеном (который был передан в API, создавший задачу). Если они совпадают, а свойство токена IsCancellationRequested возвращает значение true, задача интерпретирует его как подтверждение отмены и переход в состояние Отменено.
PS
Если вы включены. Net Core или 4.5+, Task.Run
предпочтительнее заводского подхода.