Почему создание одного ReceiverPort приводит к зависанию виртуальной машины Dart?

e.g.:

import 'dart:isolate';

void main() { var p = new ReceivePort(); }

Это приведет к зависанию всей виртуальной машины, пока я не нажму Ctrl-C. Почему это?


person kirbyfan64sos    schedule 06.05.2017    source источник


Ответы (3)


Функция Dart main работает немного иначе, чем на других платформах. Это скорее «инициализация», чем что-либо еще; он может выйти, и приложение может продолжить работу. Приложение Dart VM остается активным, если оно прослушивает события. Обычно это означает один или несколько открытых Stream. ReceivePort это Stream. Закрытие этого потока приведет к завершению приложения.

Вы можете убедиться в этом, запустив этот скрипт с помощью dart --observe script.dart и просмотрев приложение в Observatory. Вы заметите, что у вас есть один изолят, и он «бездействует» — это означает, что есть открытые порты, ожидающие сообщений. Вы можете щелкнуть «просмотреть порты» на панели изоляции, и ReceivePort будет единственным элементом в списке. В общем, если у вас зависает и вы не можете понять почему, запустите Observatory и проверьте, какие порты открыты.

person Joe Conway    schedule 08.05.2017

Изолят Dart остается живым до тех пор, пока ему есть чем заняться. Если вы запустите асинхронное вычисление в main, то изолят продолжит работу после завершения main, ожидая завершения вычисления. Когда дальнейшие вычисления не выполняются, программа завершается.

ReceivePort — это порт, который может получать данные откуда-то еще. Пока один из них открыт, изолят не знает, что он не выполнен. На ReceivePort может поступить новое событие, чтобы вызвать дополнительные вычисления. Сам изолят не знает, есть ли у кого-нибудь SendPort, который может отправлять ему данные, он просто предполагает, что это возможно.

Таким образом, ReceivePort поддерживает изолят и программу в живых, потому что программа не знает наверняка, что она еще не закончила вычисления. Это хорошая вещь. Вы можете создать новый изолят и заставить его ждать команд на ReceivePort без отключения этого изолята при первом простое.

Это означает, что вам нужно закрыть свои порты, когда вы закончите.

person lrn    schedule 08.05.2017

Я считаю, что поток (или веб-воркер), запущенный ReceivePort, все еще жив, и его необходимо явно закрыть, прежде чем все приложение сможет выйти. Попробуйте добавить p.close(), и если это исчезнет, ​​это объяснит.

person Randal Schwartz    schedule 06.05.2017