如何使用主要分离株中不同分离株的结果?

时间:2015-06-23 20:48:43

标签: dart dart-isolates

我对Dart和编程都很陌生。我正在尝试使用隔离区在Dart中开发一个命令行程序。我的目的是在同一个程序中再次比较它的性能,但是用线程用Java编写。

到目前为止,Dart计划看起来像这样:

  1. 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);
    }
    
  2. myIsolate.dart

    p3 0
    p1 -0.1168096561671553
    p2 0.023709338284264223
    
  3. 输出如下:

    str.contains(charsequence)

    正如您所看到的,隔离的返回值位于主隔离完成执行后。我想要的是使用隔离的结果进行进一步的计算。

    我不知道自己错过了什么。我确信这是非常愚蠢的事情,但我无法继续解决这个问题。在Java中很容易获得每个线程的结果值,但在Dart中我无法计算如何在隔离区中执行此操作。

    有什么想法吗?

2 个答案:

答案 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.lastStream.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}");
}
相关问题