In this tutorial you will learn about the Dart Isolates and its application with practical example.
Dart Isolates
Dart supports asynchronous programming which let your program run without getting blocked. Dart uses isolates in order to achieve concurrency. We can think of an Isolate corresponds to the Dart version of the Thread. However, there is a major difference with the usual implementation of “Threads” and “Isolates”. The Isolates are independent workers that do not share memory, but instead communicate by passing messages over channels, isolates are similar to actors in Erlang or web workers in JavaScript. Since isolates are communicating via passing messages thus it needs a way to serialize a message.
Create and Start an Isolate
An Isolate can be created using the spawn() method. The spawn method must be provided with an ‘entry point’ method with a single parameter. This parameter represents a port which isolate will use to send back notification messages.
Example:-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void start() async { ReceivePort receivePort= ReceivePort(); //port for isolate to receive messages. isolate = await Isolate.spawn(runTimer, receivePort.sendPort); receivePort.listen((data) { stdout.write('Receiving: ' + data + ', '); }); } void runTimer(SendPort sendPort) { int counter = 0; Timer.periodic(new Duration(seconds: 1), (Timer t) { counter++; String msg = 'notification ' + counter.toString(); stdout.write('Sending: ' + msg + ' -'); sendPort.send(msg); }); } |
Here, we have a start() method which creates a port and spawns an isolate. The start() method is marked as async so that we can await the response from the spawning of the isolate and to store a reference to the new isolate (Which is important when we want to kill a running isolate). The spawn() method provided with two parameters that is a callback function to execute runTimer(), and a port sendPort which the callback function will use to send messages back to the caller. The, start() method begin listening the receivePort for messages from the isolate. As this will receive a message, it will send it to the console output. The runTimer() method starts a Timer that fires every second in order to update a counter and send out a notification message via the port which it received when the isolate was spawned.
Stop an Isolate
The kill() method is used to stop a running isolate.
Example:-
1 2 3 4 5 6 7 |
void stop() { if (isolate != null) { stdout.writeln('Stopping Isolate...'); isolate.kill(priority: Isolate.immediate); isolate = null; } } |
Here, we have created a stop() method that will kill the running isolate and sets its reference to null. The priority of Isolate.immediate will terminate the isolate at earliest.
Complete Program In Action
Example:-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
import 'dart:io'; import 'dart:async'; import 'dart:isolate'; Isolate isolate; void start() async { ReceivePort receivePort= ReceivePort(); //port for isolate to receive messages. isolate = await Isolate.spawn(runTimer, receivePort.sendPort); receivePort.listen((data) { stdout.write('Receiving: ' + data + ', '); }); } void runTimer(SendPort sendPort) { int counter = 0; Timer.periodic(new Duration(seconds: 1), (Timer t) { counter++; String msg = 'notification ' + counter.toString(); stdout.write('Sending: ' + msg + ' -'); sendPort.send(msg); }); } void stop() { if (isolate != null) { stdout.writeln('Stopping Isolate...'); isolate.kill(priority: Isolate.immediate); isolate = null; } } void main() async { stdout.writeln('Starting Isolate...'); await start(); stdout.writeln('Press enter key to quit'); await stdin.first; stop(); stdout.writeln('Bye!'); exit(0); } |
Output-