Isolate.run în Dart

Rulează o funcție într-un izolat nou și dă rezultatul ca Future; cel mai simplu mod de a face un calcul greu în paralel.

Sintaxă
static Future<R> run<R>(FutureOr<R> computation(), {String? debugName})

Ce face Isolate.run

Isolate.run(f) creează un izolat, rulează f în el, trimite rezultatul înapoi și închide izolatul. Dacă f aruncă o eroare, future-ul se termină cu acea eroare. Între timp, izolatul principal rămâne liber (de exemplu o interfață grafică nu „îngheață”).

Funcția și rezultatul ei sunt copiate între izolate, deci trebuie să conțină doar date care se pot trimite: numere, texte, liste, map-uri, obiecte simple. Pentru mai multe calcule independente, pornește mai multe Isolate.run și așteaptă-le cu Future.wait.

Parametri

Parametru Descriere
computation Funcția rulată în izolatul nou.
debugName Opțional: numele izolatului, pentru depanare.

Ce returnează

Un Future<R> cu rezultatul funcției.

Exemple

Exemplul 1: Un calcul greu fără să blocheze main

import 'dart:isolate';

int numerePrime(int limita) {
  var numar = 0;
  for (var n = 2; n <= limita; n++) {
    var prim = true;
    for (var d = 2; d * d <= n; d++) {
      if (n % d == 0) {
        prim = false;
        break;
      }
    }
    if (prim) numar++;
  }
  return numar;
}

Future<void> main() async {
  final rezultat = Isolate.run(() => numerePrime(200000));
  print('main rămâne liber cât timp se calculează');
  print('Numere prime până la 200000: ${await rezultat}');
}

Rezultat

main rămâne liber cât timp se calculează
Numere prime până la 200000: 17984

Exemplul 2: Mai multe calcule în paralel și o eroare

import 'dart:isolate';

int suma(int de, int pana) {
  var s = 0;
  for (var i = de; i <= pana; i++) {
    s += i;
  }
  return s;
}

Future<void> main() async {
  final parti = await Future.wait([
    Isolate.run(() => suma(1, 500000)),
    Isolate.run(() => suma(500001, 1000000)),
  ]);
  print('Părți: $parti, total: ${parti[0] + parti[1]}');

  try {
    await Isolate.run(() => int.parse('nu e număr'));
  } on FormatException catch (e) {
    print('Eroare din izolat: ${e.message}');
  }
}

Rezultat

Părți: [125000250000, 375000250000], total: 500000500000
Eroare din izolat: Invalid radix-10 number

Greșeli frecvente

  • Folosești Isolate.run pentru operații scurte. Pornirea unui izolat costă timp; merită doar pentru calcule care durează măcar câteva zeci de milisecunde.
  • Funcția capturează un obiect care nu poate fi trimis (de exemplu un ReceivePort sau un fișier deschis). Apare o eroare la trimitere.

Comenzi înrudite

  • Isolate: Un fir de execuție separat, cu memoria lui; Isolate.current este izolatul în care rulează codul acum.
  • Isolate.spawn: Pornește un izolat de durată, care rulează o funcție cu un mesaj inițial; kill îl oprește.
  • Future.wait: Future.wait așteaptă mai multe future-uri în paralel și dă lista rezultatelor; Future.any dă primul rezultat terminat.