Dart Isolate中使用List.generate时compute方法未执行完成的问题
问题原因分析
核心问题是main isolate退出导致子Isolate被提前终止,具体拆解:
await Isolate.spawn(compute, model)仅等待子Isolate成功启动,并不会等待compute函数执行完毕。- main函数执行完
print("Exiting main")后,main isolate就会退出,Dart运行时会直接终止整个程序,包括仍在运行的子Isolate。 - 普通for循环执行速度更快,在main isolate退出前就完成计算并执行了
print;而List.generate需要先创建包含35000个元素的列表再迭代,整体耗时稍长,还没来得及执行到print语句,程序就因main isolate退出而终止了。
验证与解决方法
验证方法
在main函数末尾添加延迟,让main isolate不会马上退出,就能看到List.generate的代码也能正常执行:
void main(final List<String> args) async { print("Entering main"); final model = ModelClass(35000, 100); await Isolate.spawn<ModelClass>(compute, model); await Future.delayed(const Duration(seconds: 1)); // 添加延迟 print("Exiting main"); }
正确解决方法
如果需要确保子Isolate执行完成后main再退出,有两种常用方式:
方式1:使用ReceivePort监听子Isolate完成信号
import "dart:isolate"; void main(final List<String> args) async { print("Entering main"); final model = ModelClass(35000, 100); final receivePort = ReceivePort(); // 将模型和发送端口传给子Isolate await Isolate.spawn<(ModelClass, SendPort)>(computeWithPort, (model, receivePort.sendPort)); // 等待子Isolate发送完成信号 await receivePort.first; receivePort.close(); print("Exiting main"); } void computeWithPort(final (ModelClass, SendPort) args) { final model = args.$1; final sendPort = args.$2; int sum = 0; for (int value in List.generate(model.iteration, (index) => index)) { sum += value * model.multiplier; } print("The total sum is : $sum"); // 发送完成信号给main isolate sendPort.send(null); } class ModelClass { final int iteration; final int multiplier; ModelClass(this.iteration, this.multiplier); }
方式2:使用Isolate.run(Dart 2.19+)
Isolate.run会自动等待子Isolate执行完成,代码更简洁:
import "dart:isolate"; void main(final List<String> args) async { print("Entering main"); final model = ModelClass(35000, 100); // 等待子Isolate执行完毕 await Isolate.run(() => 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; } print("The total sum is : $sum"); } class ModelClass { final int iteration; final int multiplier; ModelClass(this.iteration, this.multiplier); }
内容的提问来源于stack exchange,提问作者user8234870
相关产品推荐
相关产品推荐

