Lección 17 · 17 de 20
Isolates con Isolate.run · Dart
Saque el cálculo pesado del hilo principal en Dart con Isolate.run, ejecute varios isolates en paralelo y capture sus errores.

Todo código de Dart se ejecuta dentro de un isolate: una unidad de ejecución con su propia memoria y su propio bucle de eventos. async/await sirve para esperar sin bloquear, pero no reparte el cálculo: si una función pasa un segundo calculando, el isolate principal se queda ocupado ese segundo y, en una aplicación Flutter, la interfaz se congela.
countPrimes es trabajo de CPU puro: una criba de Eratóstenes que marca los números compuestos en una lista de booleanos y cuenta los que quedan. `Isolate.run`, de dart:isolate, crea un isolate nuevo, ejecuta en él la función que recibe, devuelve el resultado como una Future y cierra el isolate. Mientras tanto, el isolate principal queda libre.
Varios Isolate.run a la vez aprovechan varios núcleos. Pueden terminar en cualquier orden, pero Future.wait devuelve los resultados en el orden de la lista y el programa los escribe al final, por eso la salida es siempre la misma. Los isolates no comparten memoria: lo que se envía y lo que vuelve se copia, así que no hay condiciones de carrera de las que preocuparse.
Si la función falla dentro del isolate, el error vuelve a quien llamó: countPrimes(-1) intenta crear una lista de tamaño negativo, lanza RangeError y el try/catch de main lo captura. En Flutter, la función compute() hace exactamente esto, y es la forma de procesar un JSON enorme o una imagen sin que la pantalla se detenga.
Código · main.dart
import 'dart:isolate';// CPU-heavy work: count the primes below [limit] with a sieve.int countPrimes(int limit) { final composite = List<bool>.filled(limit, false); var count = 0; for (var n = 2; n < limit; n++) { if (composite[n]) continue; count++; for (var m = n * n; m < limit; m += n) composite[m] = true; } return count;}Future<void> main() async { // Isolate.run runs the function in another isolate (another core) // and returns its result as a Future: main stays free meanwhile. final primes = await Isolate.run(() => countPrimes(5000000)); print('Primes below 5,000,000: $primes'); // Several isolates at once; Future.wait keeps the order of the list. final limits = [1000, 100000, 1000000]; final counts = await Future.wait([for (final n in limits) Isolate.run(() => countPrimes(n))]); for (var i = 0; i < limits.length; i++) { print('Below ${limits[i]}: ${counts[i]}'); } // An exception inside the isolate comes back to the caller. try { await Isolate.run(() => countPrimes(-1)); } on RangeError { print('The worker failed with a RangeError'); }}Salida · dart run main.dart
Primes below 5,000,000: 348513 Below 1000: 168 Below 100000: 9592 Below 1000000: 78498 The worker failed with a RangeError
Para recordar
- Cada isolate tiene su propia memoria: no comparten variables.
asyncno reparte el cálculo; otro isolate sí.Isolate.runejecuta una función en otro isolate y devuelve unaFuture.- Con
Future.wait, los resultados siguen el orden de la lista. - Los errores del isolate se capturan con
try/catchen quien espera.
Ejercicio
Escriba una función sumOfSquares(int n) que sume los cuadrados de 1 a n, y ejecute en paralelo n = 1000 y n = 1000000 con Isolate.run.