0

I have an isolate that works as expected except that execution never progresses beyond the for loop marked <--HERE. I am just learning Isolates, but it seems that even though Isolate.exit(sp,0) has been called, the isolate does not complete. After printing out the numbers, 'done' is never printed and the program just waits for nothing indefinitely.

How can I work this so that the program continues execution once the last number has been sent to the ReceviePort?

import 'dart:convert';
import 'dart:isolate';


main() async {
  await for(final n in getNumbers()){
    print(n);
  } // <--HERE
  print('done');
}

Stream<int> getNumbers() {
  final rp = ReceivePort();
  Isolate.spawn(_getNumbers, rp.sendPort);
  return rp.cast();
}

void _getNumbers(SendPort sp) async {
  // ... get json from server ...
  var jsonString = '[1,2,3,47,42,9]'; // an arbitrary amount of numbers
      var li = jsonDecode(jsonString);
      for (final num in li) {
        sp.send(num);
      }
  Isolate.exit(sp,0);
}

UPDATE:

I was able to achieve the desired behaviour by using a second receiveport for the onExit callback. But it does not feel like the cleanest solution. If anyone has a better way, please share. Here's what I'm at now (as above except getNumbers):

Stream<int> getNumbers() {
  final rp = ReceivePort();
  final rp2 = ReceivePort()..first.then((value) => rp.close());
  Isolate.spawn(_getNumbers, rp.sendPort, onExit: rp2.sendPort);
  return rp.cast();
}
SSMSJM
  • 149
  • 6
  • Indeed I did try this, However, closing the rp immediately causes the stream to emit nothing at all as it is cut off before it has a chance to send anything. Thanks for the suggestion though. – SSMSJM Aug 31 '22 at 01:33
  • Ah, the receive port is not in scope there (nor in that isolate) so I cannot reference it there :) – SSMSJM Aug 31 '22 at 02:16
  • btw cannot you use a second parameter passed to `exit` method as an 'end of stream' indicator? – pskink Aug 31 '22 at 02:46
  • I am leaning towards a solution like that with `rp.takeWhile((o)=>o!= null)`. Mixing data and signals like that is not super clean, but it works in cases where the ReceivePort stream does not contain nulls... I could also wrap all the data in some sort of stream state object, but I am just surprised there is no better way to indicate the end of the stream from the SendPort/spawned isolate side. – SSMSJM Aug 31 '22 at 03:42

0 Answers0