/
d.alekseev
/
SmartMenuBot
Обзор
Документация
Войти
/
d.alekseev
/
SmartMenuBot
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
ConsoleBot/BackgroundTasks/BackgroundTaskRunner.cs
66 строк
2 KB
d.alekseev
feat: добавить механизм фоновых задач и автосброс сценариев по таймауту
26 фев 2026, 09:13
26 фев 2026, 09:13
d397ee8
Код
Авторство
О чём код?
using System.Collections.Concurrent; namespace SmartMenuBot.BackgroundTasks { public class BackgroundTaskRunner : IDisposable { private readonly ConcurrentBag<IBackgroundTask> _tasks = new(); private Task? _runningTasks; private CancellationTokenSource? _stoppingCts; public void AddTask(IBackgroundTask task) { if (_runningTasks is not null) throw new InvalidOperationException("Tasks are already running"); _tasks.Add(task); } public void StartTasks(CancellationToken ct) { if (_runningTasks is not null) throw new InvalidOperationException("Tasks are already running"); _stoppingCts = CancellationTokenSource.CreateLinkedTokenSource(ct); static async Task RunSafe(IBackgroundTask task, CancellationToken cancellationToken) { try { await task.Start(cancellationToken); } catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { // Cancellation requested, task should stop. } catch (Exception ex) { Console.Error.WriteLine($"Error in {task.GetType().Name}: {ex}"); } } _runningTasks = Task.WhenAll(_tasks.Select(t => RunSafe(t, _stoppingCts.Token))); } public async Task StopTasks(CancellationToken ct) { if (_runningTasks is null) return; try { _stoppingCts?.Cancel(); } finally { await _runningTasks.WaitAsync(ct).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing); } } public void Dispose() { _stoppingCts?.Cancel(); _stoppingCts?.Dispose(); } } }