为什么创建单个 ReceiverPort 会导致 Dart VM 挂起?

Why does creating a single ReceiverPort cause the Dart VM to hang?

例如:

import 'dart:isolate';

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

这将使整个 VM 挂起,直到我按 Ctrl-C 组合它。这是为什么?

我相信由 ReceivePort 启动的线程(或 webworker)仍然存在,需要在整个应用程序退出之前明确关闭。尝试添加 p.close(),如果存在,那就说明了。

Dart 的 main 函数的运行方式与其他平台略有不同。它比其他任何东西都更像是 'init';它可以退出并且应用程序可以继续 运行。如果 Dart VM 应用程序正在监听事件,它就会保持活动状态。这通常意味着一个或多个打开的 Streams。 ReceivePortStream。关闭此流将终止应用程序。

您可以通过 运行 此脚本和 dart --observe script.dart 并在天文台中查看应用程序来验证这一点。您会注意到您有一个 isolate,它是 'idle' - 这意味着有打开的端口正在等待消息。您可以在隔离面板中单击 'see ports',ReceivePort 将成为列表中的唯一项目。一般来说,如果你挂了而且你不知道为什么,启动 Observatory 并检查哪些端口是打开的。

只要有事可做,Dart isolate 就会一直存活。 如果你在 main 开始一个异步计算,那么在 main 完成后 isolate 保持 运行,等待计算完成。 当没有进一步的计算时运行,程序结束。

A ReceivePort 是一个可以从其他地方接收数据的端口。只要其中一个打开,隔离就不会知道它还没有完成。新事件可能会到达 ReceivePort 以触发更多计算。 isolate 本身不知道是否有人 SendPort 可以向它发送数据,它只是假设这是可能的。

因此,ReceivePort 使隔离和程序保持活动状态,因为程序不确定它是否尚未完成计算。这是好事。您可以创建一个新的 isolate 并让它在 ReceivePort 上等待命令,而该 isolate 第一次空闲时不会关闭。

这确实意味着您需要在完成后关闭端口。