Skip to content
AgileLogics
6 min read

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.