Isolates and Concurrency
Prerequisites: The event loop
async/await lets Dart wait for many things at once on one thread.
To compute in parallel — using several CPU cores — Dart uses
isolates.
An isolate is like a separate little Dart program: it has its own memory and its own event loop, and runs on its own thread. Isolates don't share memory, so they can't have data races; they communicate by passing messages.
Isolate.run — the easy way
import 'dart:isolate';
int slowSum(int n) {
var sum = 0;
for (var i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
Future<void> main() async {
print('Starting background work...');
final result = await Isolate.run(() => slowSum(100000000));
print(result);
}
Starting background work...
5000000050000000
Isolate.run starts a new isolate, runs the function there, returns the
result as a Future, and shuts the isolate down. Meanwhile the main
isolate's event loop stays free — in a Flutter app, the UI keeps
animating smoothly.
Flutter also provides compute(function, argument), which does the
same job.
Several at once
import 'dart:isolate';
int countPrimes(int limit) {
var count = 0;
for (var n = 2; n <= limit; n++) {
var prime = true;
for (var d = 2; d * d <= n; d++) {
if (n % d == 0) {
prime = false;
break;
}
}
if (prime) count++;
}
return count;
}
Future<void> main() async {
final results = await Future.wait([
Isolate.run(() => countPrimes(100000)),
Isolate.run(() => countPrimes(200000)),
]);
print(results);
}
[9592, 17984]
Both counts run in parallel on different cores.
What can be sent
Values passed to and from isolates are copied (numbers, strings, lists, maps, and most objects). Some things can't be sent — for example, open sockets or objects holding native resources.
For long-running background workers that exchange many messages, use
Isolate.spawn with SendPort and ReceivePort.
When to use isolates
- Parsing very large JSON documents.
- Image processing, compression, encryption of large data.
- Any computation that takes more than a few milliseconds in a Flutter app.
Not for network or file I/O — that's already asynchronous and doesn't block the event loop.
On the web, isolates are not supported in the same way; use web workers instead.