Search code examples
loopsdartdart-isolates

The compute method is not executed completely when I use `List.generate` inside of it but when I use forloop the compute method is executed completely


The below program is for understanding isolates in dart. The compute method is passed to the spawned isolate. Inside of compute method summation is performed but when List.generate is used the compute function doesn't finish the execution because the print("The total sum is : $sum"); statement is never called.

Instead of using List.generate if we use simple for loop (commented line of code in compute()) the sum is calculated and also displayed.

import "dart:isolate";

void main(final List<String> args) async {
  print("Entering main");
  final model = ModelClass(35000, 100);
  await Isolate.spawn<ModelClass>(compute, model);
  print("Exiting main");
}

void compute(final ModelClass model) {
  int sum = 0;
  for (int value in List.generate(model.iteration, (index) => index)) {
    sum += value * model.multiplier;
  }
  // for (int index = 0; index < model.iteration; index++) {
  //   sum += index * model.multiplier;
  // }
  print("The total sum is : $sum");
}

class ModelClass {
  final int iteration;
  final int multiplier;

  ModelClass(this.iteration, this.multiplier);
}

Why when we use List.generate to generate a list and iterate over it the compute function doesn't finish execution?


Solution

  • Your problem is that the following does not await the spawned Isolate being done executing. Instead, it will just await on the creation of the Isolate itself.

    await Isolate.spawn<ModelClass>(compute, model);
    

    After this, your main Isolate have nothing else to do and does not have any way to later get triggered by any kind of event (e.g. from RecievePort, Timer or similar).

    Dart will therefore quit your program since your programs execution is only depended on the mail Isolate. See the following answer for a more detailed description of when Dart programs stops and does not stop: https://stackoverflow.com/a/70670962/1953515

    But in short, you need to make your main Isolate wait for some answer back from your spawned isolates if you want your program to first being stopped after all isolates are done execution.

    The compute() function in Flutter is doing that since it is designed to run a given function in a separate Isolate and then return the result back to the caller isolate. So it will automatically setup a RecievePort/SendPort pair.

    In Dart, you can do the same with the newly introduced Isolate.run introduced in Dart 2.19: https://api.dart.dev/stable/2.19.6/dart-isolate/Isolate/run.html