Isolate.spawn în Dart

Pornește un izolat de durată, care rulează o funcție cu un mesaj inițial; kill îl oprește.

Sintaxă
static Future<Isolate> spawn<T>(void entryPoint(T message), T message, {bool paused = false, bool errorsAreFatal = true, SendPort? onExit, SendPort? onError, String? debugName})
void kill({int priority = beforeNextEvent})

Ce face Isolate.spawn

Isolate.spawn(functie, mesaj) pornește un izolat nou care cheamă functie(mesaj). De obicei mesajul este un SendPort, prin care izolatul trimite rezultate înapoi. Funcția trebuie să fie de nivel de sus sau statică. Spre deosebire de Isolate.run, izolatul trăiește cât timp are ceva de făcut și poate trimite oricâte mesaje.

izolat.kill() oprește izolatul. Cu priority: Isolate.immediate se oprește cât mai repede; implicit, înainte de următorul eveniment. Cu onExit sau addOnExitListener primești un mesaj când izolatul s-a terminat.

Parametri

Parametru Descriere
entryPoint Funcția de nivel de sus rulată în izolatul nou.
message Valoarea trimisă funcției (des, un SendPort).
onExit / onError Opțional: porturi care primesc un mesaj la terminare sau la erori.
priority Pentru kill: cât de repede se oprește izolatul.

Ce returnează

spawn: un Future<Isolate>. kill: nimic.

Exemple

Exemplul 1: Un lucrător care trimite rezultate pe rând

import 'dart:isolate';

void lucrator(SendPort raspuns) {
  for (final oras in ['Iași', 'Cluj', 'Timișoara']) {
    raspuns.send('$oras are ${oras.length} litere');
  }
  raspuns.send(null);
}

Future<void> main() async {
  final port = ReceivePort();
  await Isolate.spawn(lucrator, port.sendPort);
  await for (final mesaj in port) {
    if (mesaj == null) break;
    print(mesaj);
  }
  print('lucrătorul a terminat');
}

Rezultat

Iași are 4 litere
Cluj are 4 litere
Timișoara are 9 litere
lucrătorul a terminat

Exemplul 2: Oprirea unui izolat cu kill

import 'dart:async';
import 'dart:isolate';

void ceas(SendPort port) {
  var i = 0;
  Timer.periodic(const Duration(milliseconds: 10), (_) => port.send(++i));
}

Future<void> main() async {
  final mesaje = ReceivePort();
  final iesire = ReceivePort();
  final izolat = await Isolate.spawn(ceas, mesaje.sendPort, onExit: iesire.sendPort);

  final primele = await mesaje.take(3).toList();
  print('primite: $primele');
  izolat.kill(priority: Isolate.immediate);
  await iesire.first;
  print('izolatul s-a oprit');
  iesire.close();
}

Rezultat

primite: [1, 2, 3]
izolatul s-a oprit

Greșeli frecvente

  • Dai lui spawn o funcție anonimă care capturează variabile locale ce nu pot fi trimise, sau o metodă de instanță. Cel mai sigur, folosește o funcție de nivel de sus.
  • Uiți să închizi ReceivePort-ul sau să oprești izolatul. Programul nu se mai termină.

Comenzi înrudite

  • Isolate: Un fir de execuție separat, cu memoria lui; Isolate.current este izolatul în care rulează codul acum.
  • Isolate.run: 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.
  • ReceivePort: Cutia poștală a unui izolat: un Stream cu mesajele primite; sendPort este adresa ei, close o închide.
  • SendPort: Adresa unui ReceivePort; send trimite un mesaj (o copie a datelor) către izolatul care deține portul.