4

中有一个spawnUri(uri)函数dart:isolate,但我没有找到任何示例。我已经猜到了它的用法,但失败了。

假设有 2 个文件,在第一个文件中,它会调用spawnUri第二个文件,并与之通信。

第一个.dart

import "dart:isolate";

main() {
  ReceivePort port = new ReceivePort();
  port.receive((msg, _) {
    print(msg);
    port.close();
  });
   var c = spawnUri("./second.dart");
   c.send(["Freewind", "enjoy dart"], port.toSendPort());
}

第二个.dart

String hello(String who, String message) {
   return "Hello, $who, $message";
}

void isolateMain(ReceivePort port) {
  port.receive((msg, reply) => reply.send(hello(msg[0], msg[1]));
}

main() {}

但是这个例子不起作用。我不知道什么是正确的代码,如何修复它?

4

4 回答 4

7

这是一个适用于 Dart 1.0 的简单示例。

应用程序飞镖:

import 'dart:isolate';
import 'dart:html';
import 'dart:async';

main() {
  Element output = querySelector('output');

  SendPort sendPort;

  ReceivePort receivePort = new ReceivePort();
  receivePort.listen((msg) {
    if (sendPort == null) {
      sendPort = msg;
    } else {
      output.text += 'Received from isolate: $msg\n';
    }
  });

  String workerUri;

  // Yikes, this is a hack. But is there another way?
  if (identical(1, 1.0)) {
    // we're in dart2js!
    workerUri = 'worker.dart.js';
  } else {
    // we're in the VM!
    workerUri = 'worker.dart';
  }

  int counter = 0;

  Isolate.spawnUri(Uri.parse(workerUri), [], receivePort.sendPort).then((isolate) {
    print('isolate spawned');
    new Timer.periodic(const Duration(seconds: 1), (t) {
      sendPort.send('From app: ${counter++}');
    });
  });
}

工人飞镖:

import 'dart:isolate';

main(List<String> args, SendPort sendPort) {
  ReceivePort receivePort = new ReceivePort();
  sendPort.send(receivePort.sendPort);

  receivePort.listen((msg) {
    sendPort.send('ECHO: $msg');
  });
}

构建是一个两步过程:

  1. pub build
  2. dart2js -m web/worker.dart -obuild/worker.dart.js

在此处查看完整的项目:https ://github.com/sethladd/dart_worker_isolates_dart2js_test

于 2014-01-20T04:58:39.100 回答
2

警告:此代码已过期。

用以下内容替换您的second.dart以使其工作:

import "dart:isolate";

String hello(String who, String message) {
  return "Hello, $who, $message";
}

main() {
  port.receive((msg, reply) => reply.send(hello(msg[0], msg[1])));
}
于 2013-06-25T14:39:10.763 回答
1

这个要点:https ://gist.github.com/damondouglas/8620350提供了一个工作(我测试过)Dart 1.5 示例。Isolate.spawn(...)在那里也可以找到一个例子。

在此处复制(添加导入语句):

回声飞镖:

import 'dart:isolate';
void main(List<String> args, SendPort replyTo) {
  replyTo.send(args[0]);
}

主要飞镖:

import 'dart:isolate';
import 'dart:async';
main() {
  var response = new ReceivePort();
  Future<Isolate> remote = Isolate.spawnUri(Uri.parse("echo.dart"), ["foo"], response.sendPort);
  remote.then((_) => response.first)
    .then((msg) { print("received: $msg"); });
}
于 2014-08-03T11:48:23.000 回答
1

无耻抄自 Dart Web Development › 如何使用 Isolate.spawn 的示例希望作者不要介意

生成的隔离不知道在哪里/如何响应其父级。

在父级中,您可以创建一个接收端口,它将接收来自子级隔离的所有消息。每当你产生一个隔离时,从你的 ReceivePort 传递一个 SendPort 实例(通过 Isolate.spawn 的 message 参数)。

子隔离也可以/应该创建自己的 ReceivePort,以便它可以接收消息。实例化时,子隔离必须将其自己的 SendPort(从其自己的 ReceivePort)发送到其父级(通过父级的 SendPort)。

当前的 API 本身并没有什么帮助。但它为全面实施提供了所有必要的构建块。

您可能需要将消息包装在标头中,类似于以下内容:

class _Request {
  /// The ID of the request so the response may be associated to the request's future completer.
  final Capability requestId;
  /// The SendPort we must respond to, because the message could come from any isolate.
  final SendPort   responsePort;
  /// The actual message of the request.
  final dynamic    message

  const _Request(this.requestId, this.responsePort, this.message);
}

class _Response {
  /// The ID of the request this response is meant to.
  final Capability requestId;
  /// Indicates if the request succeeded.
  final bool       success;
  /// If [success] is true, holds the response message.
  /// Otherwise, holds the error that occured.
  final dynamic    message;

  const _Response.ok(this.requestId, this.message): success = true;
  const _Response.error(this.requestId, this.message): success = false;
}

每个隔离都可以有一个像这样的单例消息总线:

final isolateBus = new IsolateBus();

class IsolateBus {
  final ReceivePort _receivePort = new ReceivePort();
  final Map<Capability, Completer> _completers = {};

  IsolateBus() {
    _receivePort.listen(_handleMessage, onError: _handleError);
  }

  void _handleMessage(portMessage) {
    if (portMessage is _Request) {
      // This is a request, we should process.
      // Here we send back the same message
      portMessage.responsePort.send(
        new _Response.ok(portMessage.requestId, portMessage.message));

    } else if (portMessage is _Response) {
      // We received a response
      final completer = _completers[portMessage.requestId];
      if (completer == null) {
        print("Invalid request ID received.");
      } else if (portMessage.success) {
        completer.complete(portMessage.message);
      } else {
        completer.completeError(portMessage.message);
      }

    } else {
      print("Invalid message received:  $portMessage");
    }
  }

  void _handleError(error) {
    print("A ReceivePort error occured:   $error");
  }

  Future request(SendPort port, message) {
    final completer = new Completer();
    final requestId = new Capability();
    _completers[requestId] = completer;

    port.send(new _Request(requestId, _receivePort.sendPort, message));

    return completer.future;
  }
}

SendPort anotherIsolatePort = ...
isolateBus.request(anotherIsolatePort, "Some message");

这只是一个架构示例。你当然可以推出自己的。这可以扩展到支持通知(没有响应的请求)、流等。

可能需要一个全局隔离注册表来跟踪来自每个隔离的所有 SendPort 实例,并最终将它们注册为服务。

于 2014-08-03T11:52:09.133 回答