Каков наилучший способ отследить состояние изолята в дротике?
Я пытаюсь отследить, работает ли изолят в настоящее время или нет (и в будущем произойдет ли ошибка) с помощью 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
Когда я запускаю этот код, единственный вывод, который я получаю: "Элемент завершен: item3"
Я ожидал следующий вывод (не обязательно по порядку, так как изоляты асинхронны): "Элемент завершен: элемент1" "Элемент завершен: элемент2" "Элемент завершен: элемент3"
Вот код, выполняемый в изолятах:
import 'dart:io';
main(List args) {
print('Hello world: standard out!');
stderr.writeln('Hello world: standard error!');
}
Похоже, закрытие теряется. Я что-то здесь не так делаю? Есть ли лучший способ отследить состояние изолята?
Заранее спасибо!
2 ответа
Если вы хотите быть абсолютно уверенными в том, что вы можете установить прослушиватели 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);
Как только вы зарегистрируете соответствующих слушателей, вы можете начать вновь созданный изолят с резюме.
Это очень похоже на предложение первоначального рукопожатия, но в этом случае оно встроено в библиотеку.
Надеюсь это поможет,
-Ivan
У меня было такое же поведение, когда изолят не делал ничего примечательного (только одно выражение для печати). Похоже, что он вышел до onExitListener
был зарегистрирован.
ДартДок из onExitListener
говорит
- Если изолят уже мертв, сообщение не будет отправлено.
Изолятный код
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'));
}