Что такое task в Swift Concurrency и зачем он нужен
Что проверяют
Понимаете ли вы разницу между структурированной и неструктурированной конкурентностью и как в Swift устроена отмена. Следом спрашивают, чем Task отличается от Task.detached и что будет с задачей, если экран закрыли.
Как отвечать
Task это единица асинхронной работы и одновременно мост из синхронного кода в асинхронный: в обработчике кнопки нельзя написать await, а внутри Task { } можно. Задача запускается сразу после создания, отдельного start() нет. Хэндл Task<Success, Failure> позволяет получить результат через await task.value или отменить работу.
Важные свойства:
- наследование контекста:
Task { }наследует актор (из@MainActor-кода задача пойдёт на главном акторе), приоритет и task-local значения.Task.detachedне наследует ничего и нужен редко; - отмена кооперативная:
cancel()только выставляет флаг. Код проверяет его черезTask.isCancelledилиtry Task.checkCancellation(), аTask.sleepи многие системные async-API сами бросаютCancellationError; - хэндл не владеет задачей: если отбросить ссылку на
Task, задача продолжит работать. Отменять её нужно явно; - структурированные задачи:
async let,withTaskGroupиwithThrowingTaskGroupсоздают дочерние задачи. Родитель не завершится, пока не завершатся они, а отмена родителя распространяется на детей; - SwiftUI: модификатор
.taskзапускает задачу при появлении вью и сам отменяет её при исчезновении, это лучше ручногоTaskвonAppear.
В Swift 6 со строгой проверкой конкурентности компилятор следит за тем, что уходит в замыкание задачи: передача не-Sendable значения, которое остаётся доступным из текущего контекста, становится ошибкой компиляции.
Где спотыкаются
Думают, что task.cancel() мгновенно останавливает работу. Цикл без проверок отмены спокойно дойдёт до конца.
Оборачивают всё подряд в Task.detached, «чтобы было в фоне». Теряются приоритет и актор, а обновление UI из такой задачи потребует явного await MainActor.run.
Забывают, что Task сильно захватывает self. Задача с бесконечным for await по уведомлениям держит контроллер в памяти после закрытия экрана, пока её не отменят.