Почему метод Cancel() объекта cancelTokenSource отменяет выполнение объекта Task, даже если токен не был передан в конструктор Task?

Можно попросить вас предоставить фрагмент кода, который находится внутри метода Main() в вашей программе?
  • 4 января 2024 г. 18:40
Ответы на вопрос 2
`Cancel()` метод объекта `CancellationTokenSource` не отменяет выполнение объекта `Task` напрямую. Этот метод устанавливает состояние токена отмены, связанного с `CancellationTokenSource`, в отмененное. Однако, чтобы отмена действительно повлияла на выполнение задачи (`Task`), задача должна периодически проверять состояние этого токена, и если токен находится в состоянии отмены, должен произойти выброс исключения `OperationCanceledException`.

Если задача не проверяет токен отмены, то вызов `Cancel()` не остановит её выполнение. Вот простой пример кода, который демонстрирует это поведение:

```csharp
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        // Создание токена отмены
        var cancellationTokenSource = new CancellationTokenSource();
        var cancellationToken = cancellationTokenSource.Token;

        // Запускаем задачу, которая проверяет токен отмены
        Task task = Task.Run(() =>
        {
            for (int i = 0; i < 5; i++)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    Console.WriteLine("Task отменен");
                    // Если задача не выбрасывает исключение, она завершится корректно,
                    // но будет иметь статус RanToCompletion вместо Canceled.
                    cancellationToken.ThrowIfCancellationRequested();
                }

                // Имитируем длительную работу
                Thread.Sleep(1000);
                Console.WriteLine($"Итерация {i}");
            }
        }, cancellationToken); // Передача токена отмены не обязательна для использования внутри задачи

        // Отменяем задачу спустя 3 секунды
        Task.Run(() =>
        {
            Thread.Sleep(3000);
            Console.WriteLine("Запрос на отмену задачи");
            cancellationTokenSource.Cancel();
        });

        try
        {
            task.Wait(); // Ожидаем завершения работы task
        }
        catch (AggregateException ae)
        {
            if (ae.InnerExceptions[0] is TaskCanceledException)
            {
                Console.WriteLine("Задача была отменена через исключение TaskCanceledException");
            }
        }
        finally
        {
            cancellationTokenSource.Dispose();
        }

        Console.WriteLine($"Задача завершена со статусом: {task.Status}");
    }
}
```

В этом примере задача проверяет, была ли запросена отмена через токен отмены. Если отмена была запрошена, выполняется вызов `cancellationToken.ThrowIfCancellationRequested()`, который генерирует исключение `OperationCanceledException`, и задача завершает своё выполнение. Также есть код, который извне через определенное время запрашивает отмену задачи с помощью `Cancel()`.

Очень важно, чтобы задача проверяла состояние токена отмены и корректно реагировала на запрос отмены, иначе задача просто будет выполнена до конца.
вообще то твой код не работает в дотнет8, при прямом копировании. ошибок не дает, но и ни чего не печатает.. поиграюсь.. а так то... смотри внимательно: 

... решения?.. ну простейшее - CancellationTokenSource2 ... не быть же второй таске вечной..
Похожие вопросы