4

Isolate.addOnExitListener(...) を使用して、isolate が現在実行されているかどうか (および将来的にエラーが発生したかどうか) を追跡しようとしています。ただし、次のコード スニペットは期待どおりに機能しません。

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」マップには、item1、item2、item3 の 3 つの値が含まれており、それぞれに異なる名前が付いています。

このコードを実行すると、「Item exited: item3」という出力のみが表示されます。

次の出力が期待されていました (isolate は非同期であるため、必ずしも順序どおりではありません): "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!');
}

閉鎖が失われているようです。ここで何か間違ったことをしていますか?分離株の状態を追跡するより良い方法はありますか?

前もって感謝します!

4

2 に答える 2

4

分離のコードが実行される前に 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);

適切なリスナーを登録したら、新しく作成したisolateをresumeで開始できます。

これは最初のハンドシェイクの提案と非常に似ていますが、この場合はライブラリに組み込まれています。


お役に立てれば、

-イヴァン

于 2015-03-26T00:06:53.773 に答える
2

アイソレートが注目に値することを何もしなかったとき(1つの印刷ステートメントのみ)、私は同じ動作をしました。onExitListenerが登録される前に終了したようです。

の DartDoc はonExitListener言う

  • アイソレートがすでに死んでいる場合、メッセージは送信されません。

分離コード

import 'dart:async' show Future, Stream;

void main(List<String> args) {
  new Future.delayed(new Duration(milliseconds: 500), 
      () =>print('isolate ${args}'));
}

追加の遅延により、希望の終了通知を受け取りました。遅延はかなり高くする必要があります:-(。

すべてが適切にセットアップされる前に、Isolate が終了しないように、初期ハンドシェイクを行うことができます。

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'));
}
于 2015-03-25T06:22:53.763 に答える