我对Dart和编程都很陌生。我正在尝试使用隔离区在Dart中开发一个命令行程序。我的目的是在同一个程序中再次比较它的性能,但是用线程用Java编写。
到目前为止,Dart计划看起来像这样:
main.dart
import "dart:async";
import "dart:isolate";
main(args, SendPort port) {
var partial = 0;
// ... do stuff ...
// args are used and partial is updated
port.send(partial);
}
myIsolate.dart
p3 0
p1 -0.1168096561671553
p2 0.023709338284264223
输出如下:
str.contains(charsequence)
正如您所看到的,隔离的返回值位于主隔离完成执行后。我想要的是使用隔离的结果进行进一步的计算。
我不知道自己错过了什么。我确信这是非常愚蠢的事情,但我无法继续解决这个问题。在Java中很容易获得每个线程的结果值,但在Dart中我无法计算如何在隔离区中执行此操作。
有什么想法吗?
答案 0 :(得分:1)
您必须等到所有流(来自您的端口)完成。其中一种方法就是这样:
import "dart:async";
import "dart:isolate";
main() {
var rPort1 = new ReceivePort();
var rPort2 = new ReceivePort();
// Defining completers which would complete when Streams are finished
Completer c1 = new Completer();
Completer c2 = new Completer();
var p1 = 0;
rPort1.listen((partial) {
print("p1 ${partial}");
p1 = partial;
rPort1.close();
}, onDone: ()=>c1.complete()); // Notice onDone callback here
var p2 = 0;
rPort2.listen((partial) {
print("p2 ${partial}");
p2 = partial;
rPort2.close();
}, onDone: ()=>c2.complete()); // And here
Isolate.spawnUri(new Uri.file("my_isolate.dart"), [0], rPort1.sendPort);
Isolate.spawnUri(new Uri.file("my_isolate.dart"), [0], rPort2.sendPort);
// Waiting for both streams to complete before summing our results
Future.wait([c1.future,c2.future]).then((_){
var p3 = p1 + p2;
print("p3 ${p3}");
});
}
对于您的任务,如果您正在等待确切的值,您可以只为这些值定义Futures,并在不等待隔离区(及其流)完成的情况下完成它们。
为此,只需将c*.complete(<value>)
移动到相应的listen()回调即可。这样的事情(未经测试):
rPort1.listen((partial) {
print("p1 ${partial}");
c1.complete(partial);
rPort1.close();
});
rPort2.listen((partial) {
print("p2 ${partial}");
c2.complete(partial);
rPort2.close();
});
...
Future.wait([c1.future,c2.future]).then((result){
var p3 = result[0] + result[1];
print("p3 ${p3}");
});
答案 1 :(得分:1)
如果你想在Dart中等待一些事情,那就应该是未来。您可以通过多种不同方式将流或端口事件转换为未来。如果有疑问,您始终可以使用Completer
从任何其他事件创建未来。
在这种情况下,它可以更轻松地完成,因为您只需要每个流中的一个事件,并且可以使用Stream.first
(或Stream.last
或Stream.single
)。
import "dart:async";
import "dart:isolate";
main() {
var rPort1 = new ReceivePort();
var rPort2 = new ReceivePort();
Future.wait([
Isolate.spawnUri(new Uri.file("my_isolate.dart"), [0], rPort1.sendPort)
.then((_) => rPort1.first,
onError: (_) => rPort1.close()),
Isolate.spawnUri(new Uri.file("my_isolate.dart"), [0], rPort2.sendPort)
.then((_) => rPort2.first,
onError: (_) => rPort2.close()),
]).then((ps) {
// Waiting for both streams to complete before summing our results
var p3 = ps[0] + ps[1];
print("p3 ${p3}");
});
}
在这里,我还等待spawnUri
返回Future
,因为如果您的隔离没有正确生成,它可能包含错误。
您也可以使用隔离包中的一些辅助函数。
import "dart:async";
import "dart:isolate";
import "package:isolate/isolate.dart";
main() async {
// A SingleResponseChannel has a send-port and a result future,
// and completes the future with the first port event.
// Warning: Only closed when event is sent on port!
// Consider setting a time-out on the channel.
var c1 = new SingleResponseChannel();
var c2 = new SingleResponseChannel();
Isolate.spawnUri(new Uri.file("my_isolate.dart"), [0], c1.port);
Isolate.spawnUri(new Uri.file("my_isolate.dart"), [0], c2.port);
var p3 = await c1.result + await c2.result;
print("p3 ${p3}");
}