我知道当一个隔离的微任务和事件队列都为空时,该隔离就会被删除,但是,我无法在文档中找到在某些情况下如何删除工作隔离的参考。
背景
让我们举个例子:
Future<void> main() {
final receivePort = ReceivePort();
final worker = await Isolate.spawn<SendPort>((_) {}, receivePort.sendPort);
await runMyProgram(receivePort, worker);
}
这里,主分离菌株正在创建一个新分离菌株(worker
),然后程序开始执行操作。
问题
当不需要新产生的分离菌株时,我如何手动将其删除?我无法在文档中明确找到此信息,因此我只能猜测。我必须这样做吗?
receivePort.close();
worker.kill();
或者仅仅像这样关闭端口就足够了?
receivePort.close();
注
我考虑过这个问题,如果工作隔离的两个队列(微任务和事件)都为空,并且我关闭了接收端口,那么它应该会被自动终止,如果是这种情况,调用receivePort.close()
就足够了!
2条答案
按热度按时间vcirk6k61#
如果要确保子隔离菌株关闭,即使它正在执行某项操作,也要调用
Isolate.kill()
。但是,正如您已经指出的,如果一个隔离示例没有更多的事件要处理,并且没有打开的端口(例如,计时器、打开的套接字、隔离示例端口等),那么它将自行退出。对于大多数情况,这是在隔离示例不再使用时处理它的理想方式,因为它消除了在隔离示例正在执行重要操作时杀死它的风险。
假设您的子隔离在完成需要的工作后能够很好地清理自己的打开端口,那么
receivePort.close()
应该足以让它关闭。h4cxqtbf2#
您可以从外部杀死一个孤立对象,方法是在一个表示该孤立对象的
Isolate
对象上使用Isolate.kill
方法(这就是为什么您应该小心地放弃这样的孤立对象,以及为什么您可以创建一个没有“杀死”功能的孤立对象,这样您可以更安全地传递)。你可以使用静态的
Isolate.exit
或者Isolate.current.kill
从内部立即杀死一个隔离菌株,它类似于Process.exit
,但是只针对一个隔离菌株。或者你可以确保你已经关闭了分离菌株中所有打开的接收端口,并停止任何操作。这是通常的方法,但如果你在分离菌株中运行其他人提供的代码,它可能会失败。他们可能会打开接收端口或启动周期性计时器,这些计时器会永远运行,而你对此一无所知。(您可以尝试将该代码包含在
Zone
中,在其中控制定时器,但这不会阻止它们创建接收端口,并且它们始终可以直接访问Zone.root
以离开您放置它们的区域。)或者,有人可能对您的分离菌株进行了Isolate.pause艾德,因此辅助代码将无法运行。如果我想 * 绝对肯定 * 某个隔离被删除,我会从与运行在该隔离中的我自己的代码进行通信开始(端口接收工作者指令)并告诉它关闭,作为我已经使用的通信协议的一部分。工作者代码可以选择使用
Isolate.exit
,当它完成时,或者关闭所有自己的资源,希望这样就足够了。我可能倾向于使用Isolate.exit
,但只能在等待现有工作任务完成之后。这样的工作任务可能挂起(等待一个永远不会完成的未来)。或者它可能被困在while (true){..can't stop, won't stop!..}
中而活锁了所有东西。在这种情况下,等待应该有一个超时。因此,我还将使用
Isolate.addOnExitHandler
监听隔离的关闭,并启动一个计时器,持续一段合理的时间,如果在计时器超时之前我没有收到“on exit”通知,或者工作进程关闭请求的一些反馈告诉我一切正常,我将升级到isolate.kill(priority: Isolate.immediate);
,它甚至可以杀死while (true) ...
循环。