Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dart 启动多个异步未来以响应事件_Dart_Dart Async - Fatal编程技术网

Dart 启动多个异步未来以响应事件

Dart 启动多个异步未来以响应事件,dart,dart-async,Dart,Dart Async,我想启动一个相当昂贵的操作来响应用户单击画布元素 mouseDown(MouseEvent e){ 打印(“输入事件处理程序”); var未来=新未来(费用函数); future.then((int值)=>重画画布(值); 打印(“完成事件处理程序”); } expensiveFunction(){ 对于(int i=0;isubscription.pause()); var canvas=新的CanvasElement(); canvas.onClick.listen((MouseEvent

我想启动一个相当昂贵的操作来响应用户单击画布元素

mouseDown(MouseEvent e){
打印(“输入事件处理程序”);
var未来=新未来(费用函数);
future.then((int值)=>重画画布(值);
打印(“完成事件处理程序”);
}
expensiveFunction(){
对于(int i=0;i<100000000;i++){
//在这里做些疯狂的事
}
}
重绘画布(int值){
//在这里做事
打印(“重画画布”);
}
我对M4 Dart的理解是,这个未来的构造函数应该异步启动“expensiveFunction”,也就是在与主构造函数不同的线程上启动。它确实以这种方式出现,因为“完成事件处理程序”会立即打印到IDE中的输出窗口中,然后在一段时间后“重新绘制画布”但是,如果我再次单击该元素,在上次单击后运行“expensiveFunction”之前,不会发生任何事情

如何使用futures在新线程上简单地启动一个计算密集型函数,这样即使第一个未来尚未完成,也可以让多个线程排队响应多次单击


谢谢。

正如在另一个回答中提到的,期货只是“未来可用价值的占位符”。它们不一定意味着并发

Dart有一个并发隔离的概念。您可以生成一个隔离来在并行线程或进程中运行一些代码

dart2js可以将隔离编译成Web Worker。Web Worker可以在单独的线程中运行

试着这样做:

导入“省道:隔离”;
expensiveOperation(发送端口replyTo){
var结果=doExpensiveThing(msg);
回复发送(结果);
}
main()异步{
var receive=new ReceivePort();
var隔离=等待隔离.spawn(expensiveOperation,receive.sendPort);
var结果=等待接收。首先;
打印(结果);
}

(我还没有测试过上面的内容,但类似的东西应该会起作用。)

正如在另一个答案中提到的,期货只是“未来可用价值的占位符”。它们不一定意味着并发性

Dart有一个并发隔离的概念。您可以生成一个隔离来在并行线程或进程中运行一些代码

dart2js可以将隔离编译成Web Worker。Web Worker可以在单独的线程中运行

试着这样做:

导入“省道:隔离”;
expensiveOperation(发送端口replyTo){
var结果=doExpensiveThing(msg);
回复发送(结果);
}
main()异步{
var receive=new ReceivePort();
var隔离=等待隔离.spawn(expensiveOperation,receive.sendPort);
var结果=等待接收。首先;
打印(结果);
}
(我还没有测试过上面的内容,但类似的东西应该可以工作。)

事件循环和事件队列 您应该注意,未来不是线程。它们不会并发运行,事实上,Dart是单线程的。所有Dart代码都在事件循环中运行

事件循环是一个循环,只要当前Dart隔离处于活动状态,它就会一直运行。当您调用
main()
启动Dart应用程序时,隔离将被创建,并且在主方法完成以及事件队列上的所有项目完成后,隔离将不再处于活动状态

事件队列是仍然需要完成执行的所有函数的集合。由于Dart是单线程的,所有这些函数都需要一次运行一个。因此,当事件队列中的一个项目完成时,另一个项目开始运行。事件队列的精确计时和调度比我可以解释我自己

因此,异步处理对于防止单个线程被某些长时间运行的执行阻塞非常重要。在UI中,长时间的进程可能会导致可视化,并阻碍应用程序的运行

期货 期货代表将来某个时候可用的价值,因此得名。当创建期货时,它会立即返回,并继续执行

与该未来相关联的回调(在您的情况下,
expensiveFunction
)通过添加到事件队列“启动”。当您从当前隔离返回时,回调将运行,并尽快将代码添加到
之后

溪流 因为根据定义,您的未来是异步的,并且您不知道它们何时返回,所以您希望对回调进行排队,以便它们保持有序

是一个发出可订阅事件的对象。当您编写
canvasElement.onClick.listen(…)
时,您需要
onClick
流的
MouseEvents
,然后使用
listen
订阅该流

您可以使用Streams对事件进行排队,并对这些事件注册回调以运行所需的代码

写什么
main(){
//用于向流中添加事件。
var controller=新的StreamController();
//当我们得到一个事件时暂停,以便一次只取一个值。
var subscription=controller.stream.listen(
()=>subscription.pause());
var canvas=新的CanvasElement();
canvas.onClick.listen((MouseEvent e){
打印(“输入事件处理程序”);
var未来=新未来(费用函数);
//在调用回调后恢复订阅。
添加(future.then(redrawCanvas.then)(subscription.resume());
打印(“完成事件处理程序”);
});
}
expensiveFunction(){
对于(int i=0;i<100000000;i++){
//在这里做些疯狂的事
}
}
重绘画布(int值){
//在这里做事
打印(“重画画布”);
}
在这里,我们通过在每次鼠标单击后暂停,然后在调用
redrawCanvas
后恢复,来排队执行
redrawCanvas
回调

更多信息 另请参见一个类似的问题

这是一个开始阅读Dart's书籍的好地方