e.g.:
import 'dart:isolate';
void main() { var p = new ReceivePort(); }
Это приведет к зависанию всей виртуальной машины, пока я не нажму Ctrl-C. Почему это?
e.g.:
import 'dart:isolate';
void main() { var p = new ReceivePort(); }
Это приведет к зависанию всей виртуальной машины, пока я не нажму Ctrl-C. Почему это?
Функция Dart main
работает немного иначе, чем на других платформах. Это скорее «инициализация», чем что-либо еще; он может выйти, и приложение может продолжить работу. Приложение Dart VM остается активным, если оно прослушивает события. Обычно это означает один или несколько открытых Stream
. ReceivePort
это Stream
. Закрытие этого потока приведет к завершению приложения.
Вы можете убедиться в этом, запустив этот скрипт с помощью dart --observe script.dart
и просмотрев приложение в Observatory. Вы заметите, что у вас есть один изолят, и он «бездействует» — это означает, что есть открытые порты, ожидающие сообщений. Вы можете щелкнуть «просмотреть порты» на панели изоляции, и ReceivePort
будет единственным элементом в списке. В общем, если у вас зависает и вы не можете понять почему, запустите Observatory и проверьте, какие порты открыты.
Изолят Dart остается живым до тех пор, пока ему есть чем заняться. Если вы запустите асинхронное вычисление в main
, то изолят продолжит работу после завершения main
, ожидая завершения вычисления. Когда дальнейшие вычисления не выполняются, программа завершается.
ReceivePort
— это порт, который может получать данные откуда-то еще. Пока один из них открыт, изолят не знает, что он не выполнен. На ReceivePort
может поступить новое событие, чтобы вызвать дополнительные вычисления. Сам изолят не знает, есть ли у кого-нибудь SendPort
, который может отправлять ему данные, он просто предполагает, что это возможно.
Таким образом, ReceivePort
поддерживает изолят и программу в живых, потому что программа не знает наверняка, что она еще не закончила вычисления. Это хорошая вещь. Вы можете создать новый изолят и заставить его ждать команд на ReceivePort
без отключения этого изолята при первом простое.
Это означает, что вам нужно закрыть свои порты, когда вы закончите.
Я считаю, что поток (или веб-воркер), запущенный ReceivePort, все еще жив, и его необходимо явно закрыть, прежде чем все приложение сможет выйти. Попробуйте добавить p.close()
, и если это исчезнет, это объяснит.