在 Dart 中跟踪 Isolate 状态的最佳方法是什么?
What is the best way to track the state of an Isolate in Dart?
我正在尝试使用 isolate.addOnExitListener(...) 跟踪隔离区当前是否 运行ning(以及将来是否出错)。然而,下面的代码片段并没有像我期望的那样工作:
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
当我 运行 这段代码时,我得到的唯一输出是:
"Item exited: item3"
我期望得到以下输出(不一定按顺序排列,因为 isolates 是异步的):
"Item exited: item1"
"Item exited: item2"
"Item exited: item3"
这是隔离区中 运行 的代码:
import 'dart:io';
main(List args) {
print('Hello world: standard out!');
stderr.writeln('Hello world: standard error!');
}
闭包好像丢失了。我在这里做错了什么吗?有没有更好的方法来跟踪隔离的状态?
提前致谢!
当 isolate 没有做任何值得注意的事情(只有一个打印语句)时,我有同样的行为。它似乎在 onExitListener
注册之前就退出了。
onExitListener
的 DartDoc 说
- If the isolate is already dead, no message will be sent.
隔离码
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'));
}
如果您想绝对确保可以在隔离的任何代码执行之前在隔离中安装 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);
一旦注册了合适的侦听器,就可以使用 resume 启动新创建的隔离。
这与初始握手的建议非常相似,但在这种情况下它是内置于库中的。
希望这对您有所帮助,
-伊万
我正在尝试使用 isolate.addOnExitListener(...) 跟踪隔离区当前是否 运行ning(以及将来是否出错)。然而,下面的代码片段并没有像我期望的那样工作:
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
当我 运行 这段代码时,我得到的唯一输出是: "Item exited: item3"
我期望得到以下输出(不一定按顺序排列,因为 isolates 是异步的): "Item exited: item1" "Item exited: item2" "Item exited: item3"
这是隔离区中 运行 的代码:
import 'dart:io';
main(List args) {
print('Hello world: standard out!');
stderr.writeln('Hello world: standard error!');
}
闭包好像丢失了。我在这里做错了什么吗?有没有更好的方法来跟踪隔离的状态?
提前致谢!
当 isolate 没有做任何值得注意的事情(只有一个打印语句)时,我有同样的行为。它似乎在 onExitListener
注册之前就退出了。
onExitListener
的 DartDoc 说
- If the isolate is already dead, no message will be sent.
隔离码
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'));
}
如果您想绝对确保可以在隔离的任何代码执行之前在隔离中安装 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);
一旦注册了合适的侦听器,就可以使用 resume 启动新创建的隔离。
这与初始握手的建议非常相似,但在这种情况下它是内置于库中的。
希望这对您有所帮助,
-伊万