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);
}
