2012-04-24 40 views
6

编辑以使问题更清楚。作为工人的镖分离物

我正在尝试在Dart中使用Isolates(或Web Workers)。我可以找到主线程和隔离线程之间通信的唯一方法是发送从主线程调用&然后。但是,这是主线程将一些数据传递给隔离区的一种好方法。

如果我希望隔离区成为生成信息的隔离区,该怎么办?就像一个游戏引擎,它可以完成工作中的所有物理,然后将更新后的世界信息发送到主线程?在JavaScript中,您可以随时发送数据。 Dart有效吗?或者我是否仍然需要等待主线程给我打电话,然后传给它?

P.S.我想知道,是否电话&然后封锁线程,直到答复完成或不?

回答

3

警告:此代码仅适用于飞镖的旧版本。它不适用于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); 
    }); 
} 

但是由于镖主线程本身就是一种隔离您可以通过使用全球端口功能将数据发送给它:

#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

+0

但有什么,如果我想我的隔离生成/更新数据?就像一个游戏引擎。它应该运行所有的计算,然后传递游戏中对象的更新状态。有没有一个有效的机制呢,还是我必须在Isolates之上构建它? – Pijusn 2012-04-25 04:25:55

+0

@Pius你不能将引用发送到隔离区,所有处理的数据都按照此处所述进行复制http://api.dartlang.org/dart_isolate/SendPort.html#send – 2012-04-25 05:24:08

+0

我不是在谈论引用。我在谈论数据。你有没有在JavaScript中使用Web Workers?您可以随时从工作人员发送数据。尽可能多的,如你所愿。工作人员可以在没有监听主线程的情况下工作并发送数据,而主线程可以简单地使用回调函数接收数据。我在说隔离中的self.postMessage函数等价。 – Pijusn 2012-04-25 14:54:51

0

您现在可以使用MessageBox类来相互沟通。该代码在收到MessageBox的接收端后立即从Isolate代码发送消息。主线程接收Isolate发送的消息并将其打印在Dartium的控制台上。一旦你收到了Sink,你就可以启动你的游戏逻辑并使用接收到的接收器对象发送更新。

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"); 
    }); 
} 
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++}'); 
    }); 
    }); 
} 
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> 
+0

上述代码适用于dart sdk版本1.14.2以及Chrome,Firefox和IE11 – user2569304 2016-03-07 18:34:21