Cómo utilizar Task Group

En un artículo anterior, vimos cómo podemos usar paralelización con async let. Sin embargo, esta técnica tiene una limitación importante: solo es útil cuando sabemos en tiempo de desarrollo cuánta concurrencia necesitamos. Es decir, la cantidad de procesos concurrentes es estática.

Para casos donde la cantidad de procesos concurrentes se determine en tiempo de ejecución, podemos usar TaskGroup. Estos contienen grupos de tareas asíncronas que se crean dinámicamente.

Para crear un TaskGroup, utilizamos withThrowingTaskGroup(of:returning:body:):

await withThrowingTaskGroup(of: String.self,
returning: [String]) { group in
...
}

Con este código creamos un TaskGroup, pasando los siguientes parámetros:

  • of indica qué tipo de datos manejarán las tareas hijas.
  • returning indica qué tipo de datos se retornará una vez ejecutadas todas las tareas del grupo.
  • operation, en este caso, usamos trailing closure, por lo que no es necesario indicar el nombre del último parámetro. Dentro de este closure, tenemos group, que es el objeto que utilizaremos para agregar las tareas hijas.

Agregar Tasks

Para agregar tareas a nuestro TaskGroup usamos el siguiente código:

await withThrowingTaskGroup(of: Void.self) { group in
group.addTask(priority: .high) {
try await fetch()
}
}

UsandoaddTask(priority:operation:) podemos pasar la prioridad opcionalmente. Si no se especifica, hereda la prioridad del contexto. También pasamos un bloque de código donde se encuentra la tarea que queremos agregar.

Existe una alternativa a este método addTaskUnlessCancelled(priority:operation:). La única diferencia es que con este la tarea solo se agregará si el TaskGroup no ha sido cancelado previamente.

Cómo cancelar Tasks dentro de un TaskGroup

TaskGroup tiene un método para cancelar las tareas que no se han ejecutado cancelAll().

await withThrowingTaskGroup(of: Void.self) { group in
group.addTask {
await fetch()
}
group.addTask {
await update()
}
if condition {
group.cancelAll()
}
}

Observa que en este ejemplo pasamos Void.self al parámetro of, por lo que no retornaremos nada.

En este caso estamos evaluando condition y si es true ejecutamos cancelAll(). Sin embargo, si alguna de las tareas agregadas previamente ha terminado, podremos ver el resultado, ya que solo se cancelan las tareas pendientes.

También, si una de las tareas hijas produce un error, las demás tareas faltantes serán canceladas.

Otra forma de que se pueda producir una cancelación es si la tarea padre del TaskGroup es cancelada.

Lidiando con las respuestas en un TaskGroup

try await withThrowingTaskGroup(of: String.self) { group in
group.addTask {
await fetch()
}
group.addTask {
await pull()
}
if condition {
group.cancelAll()
}
for try await result in group {
print(result)
}
}

En este código creamos dos tareas hijas que retornan un String utilizando las funciones asíncronas fetch() y pull(). Sin embargo, no queremos esperar a que ambas terminen para imprimir los valores retornados. En este caso, podemos usar for await que itera sobre los resultados de group. Esto es posible gracias a que group conforma a AsyncSequence e implementa next().

Cosas a tomar en cuenta

  • Si mientras trabajas en estas tareas te encuentras con una excepción en una de ellas, se cancelarán y detendrán automáticamente todas las tareas restantes en el grupo.
  • Todas las tareas dentro dentro de un grupo deben retornar el mismo tipo de datos.
  • A diferencia de Task y async let, podemos trabajar con los resultados de TaskGroup sin orden definido, mientras van terminado, para esto utilizamos .next() o for await.

Comparte este artículo

Subscríbete a nuestro Newsletter

Mantente al día en el mundo de las aplicaciones móviles con nuestro blog especializado.

Artículos semanales

Todas las semanas artículos nuevos sobre el mundo de las aplicaciones móviles.

No spam

No te enviaremos spam, solo contenido de calidad. Puedes darte de baja cuando quieras.

Contenido de calidad

Nada de contenido generado de manera automática usando ChatGPT.

Recomendaciones

Tips indispensables sobre mejores prácticas y metodologías.

© 2024 AsyncLearn