Коварный AttachExternalCancellatio
Если вы работаете с асинхронностью в Unity, то наверняка знакомы с UniTask. Это более эффективный и удобный для Unity инструмент, чем обычные шарповые Task. Github
Его удобство часто достигается за счёт разнообразного “сахара”, с которым важно не переборщить. Одна из таких “сладостей” — это метод AttachExternalCancellation, который очень часто используют не по назначению.
🔰 В чём проблема
Обычно для прерывания асинхронной операции используют CancellationToken: его передают внутрь и отслеживают.
Если во время исполнения был получен запрос на отмену, то нужно выбросить соответствующее исключение или прервать исполнение метода более мягко.
🖇️ Подробнее про это и полезные советы можно почитать здесь.
Соответственно, если это какой-то метод UniTask, например Delay, то вся логика остановки внутри уже реализована — достаточно только передать токен.
Почему-то принято считать, что AttachExternalCancellation работает таким же образом, хотя его можно приставить к любому асинхронному методу, который даже изначально и не подразумевал передачу ему токена.
UniTask и Task — это не сопрограммы, которые привязаны к циклу конкретного MonoBehaviour. Соответственно, они не смогут остановиться магическим образом, если к ним просто “сбоку” приставить токен.
❗️ AttachExternalCancellation не останавливает выполнение кода внутри задачи. Он лишь останавливает ожидание этой задачи.
Т.е. если вы делали await какого-то метода — он прекратится, но сам асинхронный метод продолжит работать.
Похожим образом работает и метод ToUniTask(CancellationToken token). Ему тоже не стоит доверять.
Продолжение — в Telegram 🗯️