Используйте токен отмены для отмены нескольких задач

Я хочу знать, как отменить Задачи. уже читал такие статьи: https://docs.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads?redirectedfrom=MSDN

Но я уже выполнил задачи и хочу знать, как сделать их отменяемыми.

Либо все сразу, а если это невозможно, то следует отменить одно задание, а затем он должен отменить следующее, пока все не будут устранены.

РЕДАКТИРОВАТЬ Правильно ли используется CancellationToken? Задачи продолжают выполняться, как я и хотел, но когда я нажимаю кнопку отмены, я получаю ошибку. Если я запускаю свою опубликованную версию, приложение просто закрывается:* введите описание изображения здесь

 void btnPause_Click(object sender, EventArgs e)
        {

            cts.Cancel();

        }
   

       async void btnStart_Click(object sender, EventArgs e)
    {
        try
        {
            cts = new CancellationTokenSource();
            var token = cts.Token;
            var t1 = Task.Run(() => START(token));
            await Task.WhenAny(new[] { t1 });
        }
        catch (OperationCanceledException)
        {
            // Handle canceled
        }
        catch (Exception)
        {
            // Handle other exceptions
        }
    }
    ///////////////////////////////////////////
    async void START(CancellationToken token)
    {
        for (int i = 0; i < 1; i++)
        {
            token.ThrowIfCancellationRequested();
            await Task.Delay(100, token);
             try { 
              
                    if ()
                    {
                        
                    }

            }catch { }  
        }
        Thread.Sleep(2000);
        var t2 = Task.Run(() => START2(token));
        await Task.WhenAny(new[] { t2});
    }
    ///////////////////////////////////////////////
   async void START2(CancellationToken token)
    {
       
        for (int i = 0; i < 10; i++)
        {
            token.ThrowIfCancellationRequested();
            await Task.Delay(100, token);
             try { 
              
                    if ()
                    {
                        
                    }

            }catch { }  
        }
        Thread.Sleep(7000);


        var t3 = Task.Run(() => MOVE(token));
        await Task.WhenAny(new[] {t3});
    }
    //////////////////////////////////////////
   async void MOVE(CancellationToken token)
    {


        for (int i = 0; i < 3; i++)
        {

            token.ThrowIfCancellationRequested();
            await Task.Delay(100, token);
            try { 
              
                    if ()
                    {

                    }

            }catch { }

        }
        var t4 = Task.Run(() => MOVE2(token));
        await Task.WhenAny(new[] {t4 });

    }

В статье, на которую вы ссылаетесь, содержится много подробностей. Что из этого тебе не понятно? Нет смысла говорить то же самое, что и в статье...

canton7 22.03.2022 14:20

Я надеялся на конструкцию, которую смогу использовать в своих задачах. В статье я не понимаю, как завершить все задачи одной кнопкой, потому что я использую ожидающие задачи. А в статье такое ощущение, что все в одной основной и одна потом выходит на задачу "DoSomeWork".. А мне нужно на нескольких задачах одновременно и я не могу найти то что ищу или я Я просто слепой и не замечаю этого постоянно. :/? Я попробовал это, и я не могу использовать токен отмены cts.Cancel(); на моей кнопке «Стоп», потому что я думаю, что это не глобально?

user18533075 22.03.2022 14:31

Вы создаете один CancellationTokenSource и передаете значение его параметра .Token (который является CancellationToken) всем своим задачам, где вы проверяете, было ли оно отменено, регулярно вызывая cancellationToken.ThrowIfCancellationRequested(), и перехватываете полученное OperationCanceledException, где это уместно. Когда ваша кнопка нажата, вы звоните cancellationTokenSource.Cancel()

canton7 22.03.2022 14:33
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Используйте CancellationTokenSource в несколько упрощенном примере:

CancellationTokenSource cts = new CancellationTokenSource();
async void Cancel_Click(object sender, EventArgs e)
{
    cts.Cancel();
}
async void btnStart_Click(object sender, EventArgs e)
{
    try{
       cts = new CancellationTokenSource();
       var token = cts.Token;
       var t1 = Task.Run(() => Start(token));
       var t2 = Task.Run(() => Start(token));
       await Task.WhenAny(new []{t1, t2});
    }
    catch(OperationCancelledException){
        // Handle canceled
    }
    catch(Exception){
        // Handle other exceptions
    }
}

void Start(CancellationToken token)
{
    for (int i = 0; i < 100; i++)
    {
         token.ThrowIfCancellationRequested();
         // Do work 
         Thread.Sleep(100);
    }
}

При нажатии кнопки сначала создается новый CancelTokenSource, а затем запускаются две задачи в фоновых потоках, обе с использованием токена из вновь созданного источника токенов. Когда нажата кнопка cancelButton, токен будет переведен в состояние отмены, и в следующий раз, когда каждый фоновый поток вызовет ThrowIfCancellationRequested, они вызовут исключение. Это поместит задачу в отмененное состояние, и в ожидании этого будет вызвано OperationCancelledException, которое необходимо поймать. Обратите внимание, что при ожидании нескольких задач вы можете получить агрегатное исключение, который упаковывает несколько исключений и должен быть распакован.

Было бы лучше, если это возможно, использовать await Task.Delay(100, token), а не Thread.Sleep, чтобы сон отменялся, как только токен отменяется. Тогда и Task.Run не нужен.

canton7 22.03.2022 16:42
Task.WhenAny? Ты собирался написать Task.WhenAll?
Theodor Zoulias 22.03.2022 16:55

спасибо за вашу работу действительно хорошо и легко понять :) У меня есть один вопрос. все мои задачи запускаются с ожиданием, потому что есть асинхронность... как я могу запустить эту задачу с ожиданием? var t1 = await Task.Run(() => RESTART(токен)); это неправильно... и мои задачи начинаются после выполнения следующей задачи... как я могу решить это с помощью вашего кода? я не хочу запускать все задачи сразу или я что-то не так понял?

user18533075 22.03.2022 17:14

я отредактировал свой пост и преобразовал свои задачи в это. это верно? Задачи продолжают выполняться, как я и хотел, но когда я нажимаю кнопку отмены, я получаю ошибку. Если я запускаю свою опубликованную версию, приложение просто закрывается. если я отредактирую свой код, как ваш: var t1 = Task.Run(() => Start(token)); var t2 = Task.Run(() => Start(token)); затем он запускает две задачи одновременно

user18533075 22.03.2022 17:51

@steven у вас, вероятно, есть исключение, закрывающее ваше приложение, см. мою заметку об агрегатном исключении и проверьте средство просмотра событий Windows, почему ваше приложение было закрыто. Кроме того, я бы очень не рекомендовал использовать асинхронные функции таким образом. Не усложняйте задачу, выполняйте некоторую работу, связанную с вычислениями, в фоновом потоке и обрабатывайте результат в потоке пользовательского интерфейса.

JonasH 22.03.2022 21:25

Большое спасибо, мне потребовалось много времени, чтобы понять это, но я понял это сейчас. Именно так я себе это и представлял :)

user18533075 23.03.2022 12:22

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