Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bidirectional communication with isolates in Dart 2

I'm trying isolates and I'm wondering how could I spawn some of them doing heavy computations that, when the root Isolate ask them for their current computing value they respond it, "on demand".

As far as I know, the only object that can be used as message for the newly created isolates is SendPort, meaning that only the spawned isolate can communicate with the root one. I tried sending a < SendPort,ReceivePort> tuple, but as ReceivePort isn't a SendPort, it's considered as illegal.

In a nutshell:

root <-- isolate good

root <-> isolate how to?

like image 342
Nico Rodsevich Avatar asked Sep 10 '18 14:09

Nico Rodsevich


People also ask

How do you send isolate data?

Isolates, as the name suggests, are isolated units of running code. The only way to send data between them is by passing messages, similar to the way you pass messages between the client and the server or from Dart to JavaScript.

How do you use isolate in darts?

Using isolates, your Dart code can perform multiple independent tasks at once, using additional processor cores if they're available. Isolates are like threads or processes, but each isolate has its own memory and a single thread running an event loop.

Does Dart support multithreading?

Since isolates are separate, we can have more than one isolate within our app, and that's how we can have multithreaded applications using dart.


2 Answers

With Gunter's comment I made this:

import 'dart:async';
import 'dart:io';
import 'dart:isolate';

Stopwatch stopwatch = new Stopwatch();

main(args) async {
  ReceivePort rPort = new ReceivePort();
  rPort.listen((data) {
    print("<root> $data received");
    if (data is List) {
      String action = data[0];
      if (action == "register") {
        (data[1] as SendPort).send(stopwatch.elapsedMilliseconds);
      }
    }
  });
  stopwatch.start();
  await Isolate.spawn(elIsolate, rPort.sendPort);
  print("isolate spawned in ${stopwatch.elapsedMilliseconds} msecs"); //isolate spawned in 377 msecs
}

void elIsolate(SendPort sPort) {
  ReceivePort rPort = new ReceivePort();
  rPort.listen((data) {
    print("<Isolate> '$data' received"); //<Isolate> '387' received
  });
  sPort.send(["register", rPort.sendPort]);
}

While with Kevin's answer the code simplified to:

import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'package:stream_channel/stream_channel.dart';

Stopwatch stopwatch = new Stopwatch();

main(args) async {
  ReceivePort rPort = new ReceivePort();
  IsolateChannel channel = new IsolateChannel.connectReceive(rPort);
  channel.stream.listen((data) {
    print("<root> '$data' received at ${stopwatch.elapsedMilliseconds} msecs"); //<root> 'hello world' received at 1141 msecs
    channel.sink.add(stopwatch.elapsedMilliseconds);
  });
  stopwatch.start();
  await Isolate.spawn(elIsolate, rPort.sendPort);
  print("isolate spawned in ${stopwatch.elapsedMilliseconds} msecs"); //isolate spawned in 1111 msecs
}

void elIsolate(SendPort sPort) {
  IsolateChannel channel = new IsolateChannel.connectSend(sPort);
  channel.stream.listen((data) {
    print("<Isolate> '$data' received");
  });
  channel.sink.add("hello world");
}
like image 68
Nico Rodsevich Avatar answered Oct 20 '22 14:10

Nico Rodsevich


Look at IsolateChannel from the package:stream_channel.

This should provide a LOT of help for what you're trying to do.

like image 44
Kevin Moore Avatar answered Oct 20 '22 14:10

Kevin Moore