4

我正在尝试使用isolate.addOnExitListener(...)跟踪隔离当前是否正在运行(以及将来是否出错)。但是,以下代码片段无法按我的预期工作:

items.forEach((name, item) async {
      Isolate isolate = await Isolate.spawnUri(...);
      item.status = "running";
      ReceivePort receivePort = new ReceivePort();
      isolate.addOnExitListener(receivePort.sendPort);
      receivePort.listen((message){
        if (message == null) {
          print("Item exited: ${item.name}");
          item.status = "stopped";
        }
      });
});

“items”映射包含 3 个值,每个值都有不同的名称:item1、item2、item3

当我运行此代码时,我得到的唯一输出是:“Item exited: item3”

我期望以下输出(不一定按顺序,因为隔离是异步的):“项目退出:项目 1”“项目退出:项目 2”“项目退出:项目 3”

这是在隔离区中运行的代码:

import 'dart:io';
main(List args) {
  print('Hello world: standard out!');
  stderr.writeln('Hello world: standard error!');
}

似乎关闭正在丢失。我在这里做错了吗?有没有更好的方法来跟踪隔离的状态?

提前致谢!

4

2 回答 2

4

如果您想确保在执行任何隔离的代码之前可以在隔离中安装 onExit 和 onError 侦听器,那么您可以生成已暂停的隔离。请参阅有关spawnUri的文档。

这是一个例子:

var isolate = await Isolate.spawnUri(myUri, args, message, paused: true);
var receivePort = new ReceivePort();
isolate.addOnExitListener(receivePort.sendPort);

receivePort.listen((message){
  if (message == null) { // A null message means the isolate exited
    print("Item exited: ${item.name}");
    item.status = "stopped";
  }
});

isolate.resume(isolate.pauseCapability);

一旦你注册了合适的监听器,你就可以使用resume启动新创建的隔离。

这与初始握手的建议非常相似,但在这种情况下,它是内置于库中的。


希望这可以帮助,

-伊万

于 2015-03-26T00:06:53.773 回答
2

当隔离没有做任何值得注意的事情(只有一个打印语句)时,我有同样的行为。似乎它在onExitListener注册之前就退出了。

DartDoconExitListener

  • 如果隔离已经死亡,则不会发送任何消息。

隔离代码

import 'dart:async' show Future, Stream;

void main(List<String> args) {
  new Future.delayed(new Duration(milliseconds: 500), 
      () =>print('isolate ${args}'));
}

随着额外的延迟,我得到了想要的退出通知。延迟需要相当高:-(。

您可以进行一些初始握手以确保在正确设置所有内容之前隔离不会退出

import 'dart:isolate';
import 'dart:async' show Future, Stream, Completer;
import 'dart:io' as io;

class Item {
  String name;
  String status;
  Item(this.name);
}

void main() {
  final items = {'a': new Item('a'), 'b': new Item('b'), 'c': new Item('c')};
  items.forEach((name, item) async {
    ReceivePort receivePort = new ReceivePort();
    SendPort sendPort = receivePort.sendPort;
    Isolate isolate = await Isolate.spawnUri(
        Uri.parse('isolate.dart'), [sendPort, name], null);
    receivePort.listen((message) {
      if (message is SendPort) {
        message.send('connected');
      } else if (message == null) {
        print("Item exited: ${item.name}");
        item.status = "stopped";
      } else {
        print("Message: ${message}");
      }
    });
    isolate.addOnExitListener(receivePort.sendPort);
    item.status = "running";
  });
}
import 'dart:isolate';

void main(List<String> args) {
  SendPort sendPort = (args[0] as SendPort);
  var receivePort = new ReceivePort();
  sendPort.send(receivePort.sendPort);
  // keeps the isolate alive at least until the first messgae arrives
  receivePort.first.then((e) => print('isolate received: $e'));
}
于 2015-03-25T06:22:53.763 回答