Как установить тайм-аут для задачи, а затем прервать ее

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine($"The main thread is {Thread.CurrentThread.ManagedThreadId}");
        var cts = new CancellationTokenSource();
        Person p = new Person { Name = "Apple" };
        try
        {
            cts.CancelAfter(TimeSpan.FromSeconds(3));//limited to 3 seconds
            DoSth(p).Wait(cts.Token);
        }
        catch
        {

        }
        Console.WriteLine(cts.Token.IsCancellationRequested);
        Thread.Sleep(3000);
        Console.ReadLine();
    }

    static async Task DoSth(Person p)
    {
        await Task.Run(() =>
        {
            p.Name = "Cat";
            Thread.Sleep(5000); 
            
            Console.WriteLine($"The async thread is {Thread.CurrentThread.ManagedThreadId}");
        });
    }
}

Как вы можете видеть код выше, я получил результат:

The main thread is 1
True
The async thread is 4

Кажется, что метод все еще работает после отмены? Можно ли прервать задание через какое-то время? Когда я пытаюсь использовать Thread.Abort(), я получаю предупреждение о том, что этот метод устарел.

Вы отменяете задачу в ожидании, но не отменяете задачу. Мы видим это, потому что сама задача не имеет совместной отмены и не получает CancellationToken.

DiplomacyNotWar 08.04.2022 10:44

Вещи, которые я нахожу здесь странными: использование Thread.Sleep в async Task Main вместо await Task.Delay. Вызов DoSth(p).Wait(cts.Token); вместо await DoSth(p) или, возможно, await DoSth(p, cts.Token);, если вы измените его, чтобы получить CancellationToken. Пустой улов, который просто проглатывает любые исключения, тоже не очень хорош.

DiplomacyNotWar 08.04.2022 10:45
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
37
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы хотите прервать задачу через 3 секунды, вам нужно отправить токен в функцию. Если вы используете Task.Delay и отправляете токен, который вызовет исключение при отмене и прервет задачу.

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine($"The main thread is {Thread.CurrentThread.ManagedThreadId}");
        var cts = new CancellationTokenSource();
        Person p = new Person { Name = "Apple" };
        try
        {
            cts.CancelAfter(TimeSpan.FromSeconds(3));//limited to 3 seconds
            await DoSth(p, cts.Token);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message); //task was canceled
        }
        Console.WriteLine(cts.Token.IsCancellationRequested);
        await Task.Delay(3000);
        Console.ReadLine();
    }

    static async Task DoSth(Person p, CancellationToken ct)
    {
        p.Name = "Cat";
        await Task.Delay(5000, ct); //Will throw on cancellation, so next row will not run if cancelled after 3s.
        Console.WriteLine($"The async thread is {Thread.CurrentThread.ManagedThreadId}");
    }
}

public class Person
{
    public string Name { get; set; }
}

Другие вопросы по теме