Как в GCD отменить выполняющуюся задачу?

«Как в GCD отменить выполняющуюся задачу?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

GCD не предоставляет прямого механизма отмены уже запущенной задачи, но есть несколько обходных решений:

1. DispatchWorkItem (отмена до выполнения)

let workItem = DispatchWorkItem {
    print("Эта задача может быть отменена")
}

// Запланировать выполнение
DispatchQueue.global().asyncAfter(deadline: .now() + 0.5, execute: workItem)

// Отменить до начала выполнения
workItem.cancel()

2. Флаг отмены для выполняющихся задач

class CancellableTask {
    private var isCancelled = false
    private let queue = DispatchQueue(label: "com.example.task", attributes: .concurrent)

    func start() {
        queue.async { [weak self] in
            guard let self = self else { return }

            for i in 1...100 {
                // Периодическая проверка флага
                if self.isCancelled {
                    print("Задача отменена на шаге (i)")
                    return
                }

                // Полезная работа
                Thread.sleep(forTimeInterval: 0.1)
            }
        }
    }

    func cancel() {
        queue.async(flags: .barrier) {
            self.isCancelled = true
        }
    }
}

3. OperationQueue (предпочтительный способ)

let operationQueue = OperationQueue()
let operation = BlockOperation {
    // Длительная операция
}

operationQueue.addOperation(operation)

// Отмена операции
operation.cancel()

Рекомендации:

  • Для сложных сценариев используйте OperationQueue с поддержкой зависимостей и отмены
  • В современных Swift проектах предпочитайте async/await с Task и Task.checkCancellation()
  • Всегда реализуйте периодическую проверку флагов отмены в длительных операциях