dartdart-isolatesdart-2

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?


Solution

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