Isolates operate on its own threads, where async operations operate on the main thread.
Bidirectional communication
Bidirectional communication between the main thread and isolate1/isolate2 and between isolate2 and isolate1 (with the help of the main thread).
import 'dart:io'; import 'dart:isolate'; main(List<String> args) async { ReceivePort isolate1ToMainStream = new ReceivePort(); ReceivePort isolate2ToMainStream = new ReceivePort(); SendPort? mainToIsolateStream1; isolate1ToMainStream.listen((input) { Map data = input as Map; if (data['type'] == 'sendPort') { mainToIsolateStream1 = data['value']; mainToIsolateStream1!.send('Message from Main'); } else { print('Message recieved in Main: ${data['value']}'); } }); isolate2ToMainStream.listen((input) { Map data = input as Map; switch (data['type']) { case 'sendPort': SendPort mainToIsolateStream = data['value']; mainToIsolateStream.send('Message from Main'); break; case 'redirect': if (mainToIsolateStream1 != null) { mainToIsolateStream1!.send(data['value']); } break; case 'message': print('Message recieved in Main: ${data['value']}'); break; default: print('Undefined'); } }); Isolate isolate1 = await Isolate.spawn(myIsolate1, isolate1ToMainStream.sendPort); Isolate isolate2 = await Isolate.spawn(myIsolate2, isolate2ToMainStream.sendPort); await stdin.first; isolate1.kill(priority: Isolate.immediate); isolate2.kill(priority: Isolate.immediate); isolate1ToMainStream.close(); isolate2ToMainStream.close(); } //Isolate1 void myIsolate1(SendPort isolateToMainStream) { ReceivePort mainToIsolateStream = ReceivePort(); mainToIsolateStream.listen((data) { print('Message recieved in Isolate1: $data'); }); isolateToMainStream.send({ 'type': 'sendPort', 'value': mainToIsolateStream.sendPort, }); isolateToMainStream.send({ 'type': 'message', 'value': 'Message from Isolate1', }); } // Isolate2 void myIsolate2(SendPort isolateToMainStream) { ReceivePort mainToIsolateStream = ReceivePort(); mainToIsolateStream.listen((data) { print('Message recieved in Isolate2: $data'); }); isolateToMainStream.send({ 'type': 'sendPort', 'value': mainToIsolateStream.sendPort, }); isolateToMainStream.send({ 'type': 'message', 'value': 'Message from Isolate2', }); isolateToMainStream.send({ 'type': 'redirect', 'value': 'Message from Isolate2 to isolate1', }); }
Another example where the messages when isolates are spawn are a class.
import 'dart:io'; import 'dart:isolate'; import 'dart:math'; //Isolate operate on its own thread, //where async operations operate on the main thread. List<Isolate> isolates; class Arguments { String name; String message; SendPort sendPort; Arguments({this.name, this.message, this.sendPort}); } ///Crate isolates void start() async { isolates = new List(); ReceivePort receivePort = ReceivePort(); Arguments arguments1 = Arguments(name: 'Isolate number 1', message: '100000000', sendPort: receivePort.sendPort); Arguments arguments2 = Arguments(name: 'Isolate number 2', message: '10000000', sendPort: receivePort.sendPort); //Create two isolates isolates.add(await Isolate.spawn(calculation, arguments1)); isolates.add(await Isolate.spawn(calculation, arguments2)); //isolates.add(await Isolate.spawn(someOtherThing, someOtherArguments)); //Listen for messages from the isolates receivePort.listen((data) { print('Data: $data'); }); } //Just do some heavy calculations void calculation(Arguments arguments) { int _total = int.parse(arguments.message); for (int _a = 0; _a < _total; _a++) { double _tmp = sin(_a) * cos(_a); if (_a % (_total / 10) == 0) { String msg = '${arguments.name} status $_a'; arguments.sendPort.send(msg); } } } //Kill the isolates void stop() { for (Isolate i in isolates) { if (i != null) { i.kill(priority: Isolate.immediate); i = null; print('Killed'); } } } void main() async { await start(); print('Press enter to exit'); await stdin.first; stop(); exit(0); }