Обернуть асинхронную задачу в DispatchWorkItem в Swift, чтобы сделать ее отменной?

У меня есть класс с асинхронными методами. Все способы самые простые:

      class SomeClass {
   func someFunc(params: SomeParams, completion: ((SomeResult) -> ())?) {
      ... //some code where completion is called asynchronously, not only with DispatchQueue.async
   }
   ...//other methods
}

Теперь мне нужно добавить возможность отмены таких задач, но я не несу за это ответственности, поэтому такой код следует поместить в другой класс снаружи.SomeClass. Они рекомендуют использовать, но как правильно обернуть в него такие асинхронные вызовы?

Примечание: есть вопросы и ответы как заменитьDispatchQueue.global().asyncсDispatchWorkItem, а не об обертке существующих задач

1 ответ

Я знаю, что вы уже решили свою проблему, но ради будущих читателей и в ответ на главный вопрос, можете ли вы «Обернуть асинхронную задачу в Swift, чтобы сделать ее отменяемой?», ответ таков: нет, просто обернуть его внутри обычно недостаточно. Как сообщает нам документация (выделено нами):

Отмена приводит к немедленному возврату будущих попыток выполнить рабочий элемент. Отмена не влияет на выполнение уже начатого рабочего элемента.

Если вы уже начали, это просто устанавливаетisCancelledсвойство того, что вы можете проверить с помощью некоторой вычислительно интенсивной процедуры. Но для многих асинхронных задач (например, сетевых запросов) это будет иметь ограниченную полезность.

Хуже того, он не очень хорошо подходит для переноса задачи, которая сама по себе является асинхронной. Обычно рабочий элемент завершается сразу после запуска асинхронной задачи, не дожидаясь ее завершения (если только вы не сделаете что-то неуклюжее и хрупкое, например использование семафоров; настолько, что это лучше всего рассматривать как антишаблон) .

Вам действительно необходимо включить логику отмены в . Исторически мы часто добивалисьOperationподклассы (основанные на платформе GCD), потому что затем мы можем переопределитьcancelчтобы вызвать отмену асинхронной задачи. Или в наши дни мы могли бы воспользоваться автоматическим распространением отмены, предлагаемым параллелизмом Swift. async-await. Или, похоже, вы добились этого с помощью объединения .

Итак, суть в том, что это зависит от того, чтоsomeFuncделал, ноDispatchWorkItemчасто имеет ограниченную полезность, несмотря на (очень простую) поддержку отмены.

Другие вопросы по тегам