DEV Community

GoyesDev
GoyesDev

Posted on

[SC] Usando Taks inmediatas

Preguntas guía

¿Cuál es la diferencia fundamental entre Task y Task.immediate en cuanto a cuándo empieza a ejecutarse el trabajo?

Task.immediate empieza ejecutando de forma síncrona el código definido dentro del bloque de trabajo, hasta que encuentra el primer punto de suspensión real. En este punto, continua con el trabajo fuera del Task.

¿Qué significa exactamente que una tarea inmediata "corre hasta el primer punto de suspensión real"?

El primer punto de suspensión real aparece cuando alguna operación costosa (e.g. I/O, actor ocupado, etc) cause que la tarea tenga que esperar.

Si antes de ese punto hay una salida temprana o un código síncrono simple, Task.immediate puede ejecutarlo como si fuera síncrono (sin cambiar al contexto asíncrono).

¿En qué escenarios concretos tiene sentido usar Task.immediate en lugar de un Task regular?

  • Empezar la ejecución de código asíncrono desde un contexto síncrono, preservando el orden.
  • Necesito cambiar rápidamente parte del estado del actor que va a ser usado después del Task.immediate.
  • Salir tempranamente del bloque definido en Task.immediate con una condición sencilla.

¿Qué es el overhang y por qué es especialmente peligroso en el MainActor?

overhang es ejecutar una cantidad significativa de código síncrono en un executor antes del primer punto de suspensión.

Si defino un método como @MainActor, y dentro de Task.immediate empiezo haciendo un trabajo síncrono muy demorado (e.g. que tome 300 milliseconds), esto va a bloquear la interfaz gráfica.

@MainActor
func handleSearchQuery(_ query: String) {
  Task.immediate {
    let results = expensiveLocalSearch(query)
    await updateResults(results)
  }
}
Enter fullscreen mode Exit fullscreen mode

¿Cómo se comporta Task.immediate { @MainActor in ... } cuando el executor actual no es el MainActor?

Cuando se usa Task.immediate { @MainActor in ... } y el executor actual es MainActor, en la práctica es como si tuviéramos código síncrono.

Sin embargo, llamar Task.immediate { @MainActor in ... } desde otro actor va a tener el mismo efecto que Task{ @MainActor in ... } (i.e. como si fuera código asíncrono e invirtiendo recursos para cambiar de contexto).

¿Qué diferencia hay entre Task.immediateDetached y Task.detached?

Task.immediateDetached (igual que su contraparte Task.detached) no hereda el contexto del actor, los valores locales de Task o la cancelación.

El aspecto "immediate" solo cambia cuándo empieza a ejecutar la tarea.

¿Por qué addImmediateTask dentro de un TaskGroup puede hacer que el trabajo se vuelva serial en lugar de paralelo?

La idea de usar un TaskGroup es para que las tareas se ejecuten de forma paralela. Si ellas hacen bastante trabajo síncrono, entonces prácticamente puede convertirse en una ejecución serial de las mismas.

El hecho de que una tarea immediate bloquee al executor antes de que se añada la siguiente tarea al grupo aparenta como si solo se ejecutara una tarea a la vez.


Comprensión propia

Sin mirar el texto, ¿puedes explicar con tus palabras qué ocurre paso a paso cuando se llama a Task.immediate desde una función sincrónica en el MainActor?

¿Cuáles son los tres casos que el autor menciona como válidos para usar tareas inmediatas?


Repaso crítico

¿Qué criterio usarías para decidir entre Task, Task.immediate y Task.detached en un caso real de tu propio código?


Bibliografía

Top comments (0)