Dart Isolate Spawn
Isolate.spawn starts a separate isolate that stays alive to do work. The two isolates talk by sending messages through ports.
A worker that doubles a number
The worker receives a record holding the reply port and the number 21. It sends back double the number, and the main isolate prints the awaited reply.
import 'dart:isolate';
void worker((SendPort, int) message) {
var (replyTo, value) = message;
replyTo.send(value * 2);
}
Future<void> main() async {
var port = ReceivePort();
await Isolate.spawn(worker, (port.sendPort, 21));
var reply = await port.first;
print('reply: $reply');
}A worker that shouts a word
The same pattern carries a word instead of a number. The worker sends back the word in capitals.
import 'dart:isolate';
void worker((SendPort, String) message) {
var (replyTo, word) = message;
replyTo.send(word.toUpperCase());
}
Future<void> main() async {
var port = ReceivePort();
await Isolate.spawn(worker, (port.sendPort, 'dart'));
var reply = await port.first;
print(reply);
}The same worker spawned twice
Each spawn gets its own ReceivePort, so each reply stays separate. The replies print in input order, 9 then 16.
import 'dart:isolate';
void worker((SendPort, int) message) {
var (replyTo, value) = message;
replyTo.send(value * value);
}
Future<void> main() async {
var firstPort = ReceivePort();
var secondPort = ReceivePort();
await Isolate.spawn(worker, (firstPort.sendPort, 3));
await Isolate.spawn(worker, (secondPort.sendPort, 4));
var first = await firstPort.first;
var second = await secondPort.first;
print(first);
print(second);
}Example
import 'dart:isolate';
int factorial(int n) {
var result = 1;
for (var i = 2; i <= n; i++) {
result = result * i;
}
return result;
}
void worker((SendPort, int) message) {
var (replyTo, value) = message;
replyTo.send(factorial(value));
}
Future<void> main() async {
var firstPort = ReceivePort();
var secondPort = ReceivePort();
await Isolate.spawn(worker, (firstPort.sendPort, 5));
await Isolate.spawn(worker, (secondPort.sendPort, 6));
var first = await firstPort.first;
var second = await secondPort.first;
print('5 factorial: $first');
print('6 factorial: $second');
}Key points
- Isolate.spawn takes a top-level entry function and one message to pass to it.
- The entry function runs in the new isolate, not in the main isolate.
- A ReceivePort receives messages, and its SendPort is the address other isolates send to.
- Ports are the only channel between isolates, because isolates share no memory.
- A message must be a sendable value, and a record of sendable values is sendable.
- The main isolate awaits the reply, so the printed result never depends on timing.
In this example, two workers each compute one factorial and send the result back through their own port. The main isolate awaits the first reply and then the second, so 120 prints before 720.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท DartPad
Exercise
How does a spawned worker return its result to the main isolate?