DEV Community

GoyesDev
GoyesDev

Posted on

[GCD] Cancelando un DispatchWorkItem

En una entrevista técnica se presentó el escenario hipotético donde tendría crear una tarea asíncrona, y luego cancelarla. Luego se me preguntó: "¿Qué técnica de concurrencia usaría? (i.e. GCD, OperationQueue o Swift-Concurrency)?".

Respondí que mi respuesta dependía de las condiciones específicas de mi sistema. ¿Tengo permitido usar Swift-Concurrency? Si me es posible, elegiría esto, dada la facilidad de entender el método task.cancel(), junto con la validación de estado a través de isCancelled o checkCancellation().

Enseguida el entrevistador me dijo que no se me era permitido: Puedo usar GCD u OperationQueue.

Respondí que usaría GCD, crearía un DispatchWorkItem y luego lo cancelaría.

El entrevistador me dijo que un DispatchWorkItem no se podía cancelar y que por eso se usaba un OperationQueue cuando esta situación se podía presentar.

Pregunté si acaso DispatchWorkItem no funcionaba igual que un Task en el sentido que se podía cancelar y luego validar manualmente el estado (que sería invocar workItem.cancel() y validar con isCancelled) a lo que respondió que no era posible.

En realidad sí es posible, y se cancela de la misma forma que un Task: Para detener un DispatchWorkItem que ya haya iniciado, debo verificar internamente su estado de cancelación.

En Swift:

func testDispatchItems() {
  let queue = DispatchQueue.global()

  var item: DispatchWorkItem?

  item = DispatchWorkItem { [weak self] in
    for i in 0 ... 10_000_000 {
      if item?.isCancelled ?? true { break }
      print(i)
      self?.heavyWork()
    }
    item = nil
  }

  queue.async(execute: item!)
  queue.asyncAfter(deadline: .now() + 5) {
    item?.cancel()
    item = nil
  }
}
Enter fullscreen mode Exit fullscreen mode

En Objective-C se usaría dispatch_block_cancel para cancelar un bloque creado con dispatch_block_create, e internamente se tendría que validar su estado con dispatch_block_testcancel.

Top comments (0)