Ответ
Да, Task можно отменить, используя механизм CancellationToken.
Основной подход:
- Создайте
CancellationTokenSource. - Передайте
cancellationTokenв задачу. - Задача должна периодически проверять статус отмены.
- Вызовите
cancel()для инициации отмены.
Пример создания и отмены задачи:
let tokenSource = CancellationTokenSource()
let task = Task {
// Периодически проверяем отмену
for i in 1...10 {
try Task.checkCancellation() // Выбрасывает CancellationError при отмене
print("Processing item (i)")
try await Task.sleep(nanoseconds: 1_000_000_000)
}
}
// Через 3 секунды отменяем задачу
Task {
try await Task.sleep(nanoseconds: 3_000_000_000)
tokenSource.cancel()
print("Task cancellation requested")
}
Ключевые моменты:
- Отмена кооперативная — задача должна явно проверять
Task.isCancelledили вызыватьTask.checkCancellation(). - Состояние задачи — после отмены
task.isCancelledбудетtrue, ноtask.isCompletedстанетtrueтолько после завершения работы задачи. - Очистка ресурсов — используйте
deferилиTask.checkCancellation()для корректного освобождения ресурсов при отмене.
Проверка отмены вручную:
Task {
while !Task.isCancelled {
// Выполняем работу
await processNextItem()
}
// Выполняем финализацию
cleanupResources()
} Ответ 18+ 🔞
А, ну так вот, слушай, про отмену задач в этих ваших асинхронных делах. Всё просто, как три копейки, но есть нюансы, блядь.
Короче, главный инструмент — это CancellationTokenSource. Представь его как такую красную кнопку, на которую можно нажать и сказать «всё, пиздец, заканчивай».
Как это работает, по шагам:
- Создаёшь себе эту самую «кнопку» —
CancellationTokenSource. - Берёшь у неё токен и суёшь его в свою задачу.
- Внутри задачи ты должен быть не лох и периодически спрашивать: «А не отменили ли меня, случайно?»
- Когда захочешь всё остановить — просто жмёшь
cancel()на этой кнопке. Всё, приехали.
Вот смотри, как это выглядит в коде, ёпта:
let tokenSource = CancellationTokenSource() // Вот она, наша волшебная кнопка
let task = Task {
// Делаем что-то полезное, но с оглядкой
for i in 1...10 {
try Task.checkCancellation() // Спрашиваем: "Меня не выебали?" Если да — вылетает ошибка.
print("Обрабатываю элемент (i)")
try await Task.sleep(nanoseconds: 1_000_000_000) // Спим секунду
}
}
// А вот отдельная задачка, которая через 3 секунды нажмёт на красную кнопку
Task {
try await Task.sleep(nanoseconds: 3_000_000_000)
tokenSource.cancel() // Бдыщ! Отмена!
print("Запросили отмену задачи, пиздец")
}
Важные моменты, которые надо понимать, чтобы не обосраться:
- Отмена — она кооперативная, сука. Это не как в армии — «раз! и всё». Задача сама должна быть умной и проверять, не пора ли ей сворачиваться. Если она будет тупо молотить цикл без проверок, то хоть обосци токеном — она не остановится.
- Состояние задачи. После вызова
cancel(), у задачиisCancelledстанетtrue. НоisCompletedстанетtrueтолько когда она реально завершит свою работу (или вылетит по ошибке отмены). - Уборка за собой. Всегда думай об очистке ресурсов. Используй
deferили лови ошибку отмены, чтобы закрыть файлы, сетевые соединения и прочую хуйню. Не будь свиньёй.
Можно и вручную проверять, если не хочешь, чтобы тебя выкидывало с ошибкой:
Task {
// Работаем, пока не прилетит команда "стоп"
while !Task.isCancelled {
// Делаем что-то тяжёлое
await processNextItem()
}
// А вот тут уже делаем финальные штрихи, типа "всё, я закончил, можно убирать инструменты"
cleanupResources()
}
Вот и вся магия. Главное — не забывай про эти проверки, а то будет как в том анекдоте: «запустил задачу, а она до сих пор бежит, ебать её в сраку».