Как остановить бесконечный цикл?

Рейтинг: 0Ответов: 1Опубликовано: 12.02.2023

Есть телеграмм-бот, у него есть команда, которая выполняется бесконечно, пока не придет апдейт с командой "/stop".

public override async void Execute(String command, Message message, ITelegramBotClient client, State state)
{
   
    if (message.Text == "/stop")
        StopLoop();
    
    if(message.Text == "/start")
        StartLoop(message,client);

}
   
private CancellationTokenSource _cts;
private async Task RunLoopAsync(CancellationToken token,Message message, ITelegramBotClient client )
{
    try
    {
        while (true)
        {
            await client.SendTextMessageAsync(message.Chat.Id, "send", cancellationToken: token);
            await Task.Delay(10000, token); 
        }
    }
    catch (OperationCanceledException)
    { } 
}
private async void StartLoop(Message message, ITelegramBotClient client)
{
    if (_cts != null)
        return;
    try
    {
        using (_cts = new CancellationTokenSource())
        {
            await RunLoopAsync(_cts.Token,message,client);
        }
    }
    catch (Exception ex)
    {
        // ... ex.Message
    }
    _cts = null;
}

private void StopLoop()
{
    _cts?.Cancel();
}

Для остановки цикла, я взял пример отсюда: пример

Но это не помогает. Что посоветуете сделать, чтобы можно было остановить этот цикл?

Ответы

▲ 0Принят

Спасибо @aepot за догадки, ибо они помогли. Для успешного окончания цикла, у меня в коде нужно добавить конечный автомат:

public override async void Execute(String command, Message message, ITelegramBotClient client, State state)
{
    state.ActionCommand = "/start";
    var searchState = await _context.SearchState.FindAsync((e => e.UserId == message.Chat.Id))
        .Result.FirstOrDefaultAsync()??new SearchState(){_cts = new CancellationTokenSource()};
    _cts = searchState._cts;
    
    if (message.Text == "/stop")
    {
        searchState.IsWork = "false";
        await _stateMachine.DeleteState(message.Chat.Id);
        await _context.SearchState.ReplaceOneAsync((f=>f.UserId == message.Chat.Id),searchState);
        await client.SendTextMessageAsync(message.Chat.Id, "end");
        StopLoop();
    }

    if (message.Text == "/start")
    {
        searchState.UserId = message.Chat.Id;
        searchState.IsWork = "true";
        await _context.SearchState.InsertOneAsync(searchState);
        StartLoop(message, client);

    }
}

private CancellationTokenSource _cts;
private async Task RunLoopAsync(CancellationToken token,Message message, ITelegramBotClient client )
{
    try
    {
        while (true)
        {
            var find = await _context.SearchState.FindAsync((e => e.UserId == message.Chat.Id)).Result.FirstOrDefaultAsync()??new SearchState();
            if (find.IsWork == "false")
            {
                await _context.SearchState.DeleteOneAsync(f => f.UserId == message.Chat.Id);
                return;
            }

            await _parserWorker.Work(message, client, message.Chat.Id);
            await Task.Delay(120000, token); 
        }
    }
    catch (OperationCanceledException)
    { } 
}
private async void StartLoop(Message message, ITelegramBotClient client)
{

    try
    {
        using (_cts = new CancellationTokenSource())
        {
            await RunLoopAsync(_cts.Token,message,client);
        }
    }
    catch (Exception ex)
    {
        // ... ex.Message
    }
    _cts = null;
}

private void StopLoop()
{
    _cts?.Cancel();
}