spawnUri(uri)
中有一个dart:isolate
函数,但我没有找到任何示例。我已经猜到了它的用法,但失败了。
假设有2个文件,在第一个文件中,它将为第二个文件调用spawnUri
,并与之通信。
first.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());
}
second.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() {}
但是这个例子不起作用。我不知道什么是正确的代码,如何修复它?
答案 0 :(得分:6)
这是一个适用于Dart 1.0的简单示例。
app.dart:
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++}');
});
});
}
worker.dart:
import 'dart:isolate';
main(List<String> args, SendPort sendPort) {
ReceivePort receivePort = new ReceivePort();
sendPort.send(receivePort.sendPort);
receivePort.listen((msg) {
sendPort.send('ECHO: $msg');
});
}
建设分为两个步骤:
pub build
dart2js -m web/worker.dart -obuild/worker.dart.js
请在此处查看完整项目:https://github.com/sethladd/dart_worker_isolates_dart2js_test
答案 1 :(得分: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])));
}
答案 2 :(得分:1)
这个要点:https://gist.github.com/damondouglas/8620350提供了一个工作(我测试过)的Dart 1.5示例。此处也可以找到Isolate.spawn(...)
示例。
在此处重现(添加import语句):
echo.dart:
import 'dart:isolate';
void main(List<String> args, SendPort replyTo) {
replyTo.send(args[0]);
}
main.dart:
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"); });
}
答案 3 :(得分:1)
无耻复制 Dart Web Development › Example on how to use Isolate.spawn 我希望作者不介意
产生的分离物不知道在哪里/如何回应其父母。
在父级中,您可以创建一个ReceivePort,它将接收来自子隔离区的所有消息。 无论何时生成隔离,请将它从ReceivePort传递给SendPort实例(通过Isolate.spawn的消息参数)。
子隔离可能/应该创建自己的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实例,并最终将它们注册为服务。