编辑以使问题更清晰。
我正在尝试使用Dart中的Isolates(或Web Workers)。我可以找到在主线程和隔离线程之间进行通信的唯一方法是发送和 call&那么来自主线程。但这是主线程将一些数据传递给隔离的好方法。
如果我希望隔离区成为生成信息的隔离区,该怎么办?就像一个游戏引擎,它可以完成工作中的所有物理,然后将更新的世界信息发送到主线程?在JavaScript中,您可以随时发送数据。在达特有一种有效的方式吗?或者我是否仍然需要等待主线程给我打电话然后传递给它?
P.S。我想知道,打电话&然后阻止线程,直到回复完成?
答案 0 :(得分:3)
警告:此代码仅适用于非常旧版本的Dart。它不适用于Dart 1.0或更高版本。
当你提到将消息发布到隔离区时,你需要有一个处理它的sendport。
#import('dart:isolate');
main() {
SendPort sendPort = spawnFunction(doWork);
sendPort.call("hey 1").then((String res) => print("result was: [$res]"));
sendPort.call("hey 2").then((String res) => print("result was: [$res]"));
}
doWork() {
port.receive((msg, reply) {
msg = "msg $msg";
reply.send(msg);
});
}
但是由于Dart主线程本身就是一个隔离线,您可以使用全局端口功能向其发送数据:
#import('dart:isolate');
#import('dart:io');
main() {
port.receive((data, reply) {
// in here you can access objects created in the main thread
print("handle [${data['text']}] for index ${data['index']}");
});
SendPort workPort = spawnFunction(doWork);
workPort.send("msg", port.toSendPort());
}
doWork() {
port.receive((msg, reply) {
int i = 0;
new Timer.repeating(1000, (Timer timer) {
i++;
var data = {
"text": "$msg $i",
"index": i
};
print("sending $data");
reply.send(data);
});
});
}
请注意,在隔离区之间来回传输的内容存在一定的限制,并且当前隔离区在JS和VM上的行为也不同。目前的限制很好地描述了here。
答案 1 :(得分:3)
从Dart 1.0开始,你可以使用这样的隔离物:
import 'dart:isolate';
import 'dart:async';
void doStuff(SendPort sendPort) {
print('hi from inside isolate');
ReceivePort receivePort = new ReceivePort();
sendPort.send(receivePort.sendPort);
receivePort.listen((msg) {
print('Received in isolate: [$msg]');
sendPort.send('ECHO: $msg');
});
}
void main() {
SendPort sendPort;
ReceivePort receive = new ReceivePort();
receive.listen((msg) {
if (sendPort == null) {
sendPort = msg;
} else {
print('From isolate: $msg');
}
});
int counter = 0;
Isolate.spawn(doStuff, receive.sendPort).then((isolate) {
new Timer.periodic(const Duration(seconds:1), (t) {
sendPort.send('Count is ${counter++}');
});
});
}
答案 2 :(得分:1)
这是一个例子,其中父创建了两个隔离区,然后两个隔离区也与父进程相互通信。
家长代码:
import 'dart:isolate';
import 'dart:html';
import 'dart:async';
main() {
querySelector('#output').text = 'Your Dart app is running.';
int counter = 0;
// Parent - Child 1
SendPort csendPort1;
ReceivePort receivePort1 = new ReceivePort();
// Parent - Child 2
SendPort csendPort2;
ReceivePort receivePort2 = new ReceivePort();
// Child1 - Child2
SendPort csendPort11;
SendPort csendPort12;
// Child 1
receivePort1.listen((msg) {
if (csendPort1 == null) {
csendPort1 = msg;
} else if (csendPort11 == null) {
csendPort11 = msg;
} else {
print('$msg');`enter code here`
}
});
bool child1 = false;
Isolate.spawnUri(Uri.parse('child.dart'), [], receivePort1.sendPort).then((isolate) {
print('Child 1 isolate spawned');
new Timer.periodic(const Duration(milliseconds: 500), (t) {
if (csendPort11 != null && csendPort12 != null && child1 == false) {
child1 = true;
csendPort12.send(csendPort11);
} else {
csendPort1.send('Parent-Child1: ${counter++}');
}
});
});
// Child 2
receivePort2.listen((msg) {
if (csendPort2 == null) {
csendPort2 = msg;
} else if (csendPort12 == null) {
csendPort12 = msg;
} else {
print('$msg');
}
});
bool child2 = false;
Isolate.spawnUri(Uri.parse('child.dart'), [], receivePort2.sendPort).then((isolate) {
print('Child 2 isolate spawned');
new Timer.periodic(const Duration(milliseconds: 500), (t) {
if (csendPort11 != null && csendPort12 != null && child2 == false) {
child2 = true;
csendPort11.send(csendPort12);
} else {
csendPort2.send('Parent-Child2: ${counter++}');
}
});
});
}
儿童代码:
import 'dart:isolate';
import 'dart:async';
int pcounter = 0;
int ccounter = 0;
SendPort csendPort;
void handleTimeout() {
csendPort.send("${ccounter++}");
}
main(List<String> args, SendPort psendPort) {
// Parent Comm
ReceivePort creceivePort1 = new ReceivePort();
psendPort.send(creceivePort1.sendPort);
creceivePort1.listen((msg) {
psendPort.send('Child-Parent: ${pcounter++} - ${msg}');
});
// Child-Child Comm
ReceivePort creceivePort2 = new ReceivePort();
psendPort.send(creceivePort2.sendPort);
creceivePort2.listen((msg) {
if (csendPort == null) {
csendPort = msg;
csendPort.send("${ccounter++}");
} else {
print("Child-Child: $msg");
var duration = const Duration(milliseconds: 2000);
new Timer(duration, handleTimeout);
}
});
}
HTML代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="scaffolded-by" content="https://github.com/google/stagehand">
<title>WebIsolateTest</title>
<link rel="stylesheet" href="styles.css">
<script defer src="main.dart" type="application/dart"></script>
<script defer src="packages/browser/dart.js"></script>
</head>
<body>
<div id="output"></div>
</body>
</html>
答案 3 :(得分:0)
现在,您可以使用MessageBox类以相反的方式进行通信。一旦收到MessageBox的Sink端,此代码就会从Isolate代码发送一条消息。主线程接收从Isolate发送的消息并将其打印在Dartium的控制台上。收到接收器后,您可以启动游戏逻辑并使用收到的接收器对象发送更新。
import 'dart:html';
import 'dart:isolate';
void main() {
IsolateSink isolateSink = streamSpawnFunction(myIsolateEntryPoint);
MessageBox isolateMessageBox = new MessageBox();
isolateSink.add(isolateMessageBox.sink);
isolateMessageBox.stream.listen((String data) {
print(data);
});
}
void myIsolateEntryPoint() {
stream.listen((IsolateSink messageBoxSink) {
messageBoxSink.add("Test");
});
}