Concurrency
- Dart course
- Advanced
- Lesson 82/83
- 6 min
Add parallel processing with Isolate.
Parallel computation with Isolate
Isolate is Dart's parallel execution unit. Dart is single-threaded; heavy computation blocks the main thread. Isolate.run runs a function in a separate isolate and returns the result as a Future.
Example: Future<int> heavyCompute(int n) { return Isolate.run(() => fib(n)); }. Here fib(n) is computed in a separate isolate; the main thread stays free. Isolates do not share memory; each has its own heap. So data is passed by copy. Heavy CPU work (big computation, image processing) is moved to an isolate; this keeps the interface responsive.
The heavyCompute pattern
heavyCompute is the function that runs the heavy fibonacci computation in an isolate. fib is slow in the naive form; for big n it freezes the main thread. Isolate.run moves this load to the background.
Example: int fib(int n) { if (n < 2) return n; return fib(n-1) + fib(n-2); } and Future<int> heavyCompute(int n) { return Isolate.run(() => fib(n)); }. fib(10) = 55 is deterministic. heavyCompute returns a Future; it is awaited with await. This pattern is the standard way to do background computation while keeping the interface responsive.
Practice fib and heavyCompute
Add import 'dart:isolate'; at the top. Write int fib(int n): if n < 2 return n, else return fib(n-1) + fib(n-2). Write Future<int> heavyCompute(int n) with return Isolate.run(() => fib(n)); inside. In main add print('Isolate: heavyCompute ready') and print('fib(10): ${fib(10)}').
Starter code
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';
import 'package:sqflite/sqflite.dart';
class Task {
final int id;
final String title;
Task({required this.id, required this.title});
}
abstract class TaskService {
List<Task> list();
}
class InMemoryTaskService implements TaskService {
@override
List<Task> list() => [Task(id: 1, title: 'task 1')];
}
Response taskHandler(Request req, TaskService svc) {
return Response.ok('tasks: ${svc.list().length}');
}
class SqliteTaskService {
final Database db;
SqliteTaskService(this.db);
Future<List<Task>> all() async {
final rows = await db.query('tasks');
return rows.map((r) => Task(id: r['id'] as int, title: r['title'] as String)).toList();
}
}
// import the dart:isolate library
// write the fib and heavyCompute functions (with Isolate.run)
void main() {
// print Isolate info and fib(10)
}Sample solution
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';
import 'package:sqflite/sqflite.dart';
import 'dart:isolate';
class Task {
final int id;
final String title;
Task({required this.id, required this.title});
}
abstract class TaskService {
List<Task> list();
}
class InMemoryTaskService implements TaskService {
@override
List<Task> list() => [Task(id: 1, title: 'task 1')];
}
Response taskHandler(Request req, TaskService svc) {
return Response.ok('tasks: ${svc.list().length}');
}
class SqliteTaskService {
final Database db;
SqliteTaskService(this.db);
Future<List<Task>> all() async {
final rows = await db.query('tasks');
return rows.map((r) => Task(id: r['id'] as int, title: r['title'] as String)).toList();
}
}
int fib(int n) {
if (n < 2) return n;
return fib(n - 1) + fib(n - 2);
}
Future<int> heavyCompute(int n) {
return Isolate.run(() => fib(n));
}
void main() {
print('Isolate: heavyCompute ready');
print('fib(10): ${fib(10)}');
}Expected output
Isolate: heavyCompute ready fib(10): 55
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What does Isolate.run provide?
- Encryption
- Parallel computation Correct answer
- Compression
- Serialization
Explanation: Isolate.run provides parallel computation.
2 Match the Isolate parts
| Term | Meaning |
|---|---|
Isolate |
Worker |
run |
Starts |
fib |
Fibonacci |
heavyCompute |
Heavy compute |
3 The Isolate.run call
return Isolate.____(() => fib(n));
return Isolate.run(() => fib(n));
Explanation: Isolate.run(() => fib(n)) runs the computation in an isolate.