lamnhan066/isolate_manager

How to send one message and receive multiple data asynchronously returned?

Closed this issue · 2 comments

In my example, I want to call IsolateManager.sendMessage once and receive one hundred data translated to the main thread from the isolate.

I found through debugging that IsolateManagerController calls sendResult multiple times, but IsolateManager.stream can only receive one data.

I want to know whether it's possible to achieve the desired effect without modifying isolate_manager project code, which means passing in one number and getting 100 numbers out.

https://github.com/AoEiuV020/isolate_transformer/blob/ceaf89a6ae0ac3775262b80ee1d223edf2b3d03e/apps/example/lib/src/function/prime.dart

import 'package:isolate_manager/isolate_manager.dart';

@pragma('vm:entry-point')
void findPrimeNumbersIsolateFunction(dynamic params) {
  final channel = IsolateManagerController<int, int>(params);
  findPrimeNumbersTransform(channel.onIsolateMessage).listen((message) {
    channel.sendResult(message);
  });
}
Stream<int> findPrimeNumbersTransform(Stream<int> numStream) =>
    numStream.asyncExpand((event) {
      return findPrimeNumbers(event * 10, 100);
    });

Stream<int> findPrimeNumbers(int from, int count) async* {
  int num = from;
  int found = 0;

  while (found < count) {
    if (isPrime(num)) {
      yield num;
      found++;
    }
    num++;
  }
}

bool isPrime(int n) {
  if (n <= 1) return false;
  if (n <= 3) return true;

  if (n % 2 == 0 || n % 3 == 0) return false;

  int i = 5;
  while (i * i <= n) {
    if (n % i == 0 || n % (i + 2) == 0) return false;
    i += 6;
  }
  return true;
}
  final primeIsolate = IsolateManager.createOwnIsolate(
    findPrimeNumbersIsolateFunction,
  );

  void initIsolate() {
    primeIsolate.stream.listen((event) {
      currentPrime = event;
      if (!primeController.isClosed) {
        primeController.add((index++, event));
      }
    });
    numController.stream.listen((event) {
      primeIsolate.sendMessage(event);
    });
  }

Hi @AoEiuV020

If you want to get multiple values in a single sendMessage, you can use the callback parameter like this:

await primeIsolate.sendMessage(10, callback: (value) {
  // Assume that this value is a flag or a final result that lets us know it is the last value.
  // Only this value will be sent to the `stream`.
  //
  // If this line is not set, this `sendMessage` will be stuck forever.
  if (value == -1) return true;

  return false;
});

And we need to modify the findPrimeNumbers a little bit to add a flag -1:

Stream<int> findPrimeNumbers(int from, int count) async* {
  int num = from;
  int found = 0;

  while (found < count) {
    if (isPrime(num)) {
      yield num;
      found++;
    }
    num++;
  }

  // To let the `callback` know this is the last value.
  yield -1;
}

With this way, the primeIsolate.stream seems useless.

Feel free to re-open if the issue still persists.