close
当前位置: 物联网在线 > 技术文库 > ios >

Dart异步任务与消息循环机制

Dart与消息循环机制

异步任务在Dart中随处可见,例如许多库的方法调用都会返回Future对象来实现异步处理,我们也可以注册Handler来响应一些事件,如:鼠标点击事件,I/O流结束和定时器到期。

这篇文章主要介绍了Dart中与异步任务相关的消息循环机制,阅读完这篇文章后相信你可写出更赞的异步执行代码。你也能学习到如何调度Future任务并且预测他们的执行顺序。

在阅读这篇文章之前,你最好先要了解一下基本的 Future用法 。

基本概念

如果你写过一些关于UI的代码,你就应该熟悉消息循环和消息队列。有了他们才能保重UI的绘制操作和一些UI事件,如鼠标点击事件可以被一个一个的执行从而保证UI和UI事件的统一性。

<!-- more -->

消息循环和消息队列

一个消息循环的职责就是不断从消息队列中取出消息并处理他们直到消息队列为空。

消息队列中的消息可能来自用户输入,文件I/O消息,定时器等。例如下图的消息队列就包含了定时器消息和用户输入消息。

上述的这些概念你可能已经驾轻就熟了,那接下来我们就讨论一下这些概念在Dart中是怎么表现的?

Dart的单线程执行

当一个Dart的方法开始执行时,他会一直执行直至达到这个方法的退出点。换句话说Dart的方法是不会被其他Dart代码打断的。

Note:一个Dart的命令行应用可以通过创建isolates来达到并行运行的目的。isolates之间不会共享内存,它们就像几个运行在不同进程中的app,中能通过传递message来进行交流。出了明确指出运行在额外的isolates或者workers中的代码外,所有的应用代码都是运行在应用的main isolate中。要了解更多相关内容,可以查看

正如下图所示,当一个Dart应用开始的标志是它的main isolate执行了main方法。当main方法退出后,main isolate的线程就会去逐一处理消息队列中的消息。

Dart异步任务与消息循环机制

事实上,上图是经过简化的流程。

Dart的消息循环和消息队列

一个Dart应用有一个消息循环和两个消息队列-- event队列 和 microtask队列 。

event队列包含所有外来的事件:I/O,mouse events,drawing events,timers,isolate之间的message等。

microtask 队列在Dart中是必要的,因为有时候事件处理想要在稍后完成一些任务但又希望是在执行下一个事件消息之前。

event队列包含Dart和来自系统其它位置的事件。但microtask队列只包含来自当前isolate的内部代码。

正如下面的流程图,当main方法退出后,event循环就开始它的工作。首先它会以FIFO的顺序执行micro task,当所有micro task执行完后它会从event 队列中取事件并执行。如此反复,直到两个队列都为空。

Dart异步任务与消息循环机制

注意:当事件循环正在处理micro task的时候。event队列会被堵塞。这时候app就无法进行UI绘制,响应鼠标事件和I/O等事件

虽然你可以预测任务执行的顺序,但你无法准确的预测到事件循环何时会处理你期望的任务。例如当你创建一个延时1s的任务,但在排在你之前的任务结束前事件循环是不会处理这个延时任务的,也就是或任务执行可能是大于1s的。

通过链接的方式指定任务顺序

如果你的代码之间存在依赖,那么尽量让他们之间的依赖关系明确一点。明确的依赖关系可以很好的帮助其他开发者理解你的代码,并且可以让你的代码更稳定也更容易重构。

先来看看下面这段错误代码:

// 这样写错误的原因就是没有明确体现出设置变量和使用变量之间的依赖关系 future.then(...set an important variable...); Timer.run(() {...use the important variable...});

正确的写法应该是:

// 明确表现出了后者依赖前者设置的变量值 future.then(...set an important variable...) .then((_) {...use the important variable...});

为了表示明确的前后依赖关系,我们可以使用 then()() 来表明要使用变量就必须要等设置完这个变量。这里可以使用 whenComplete() 来代替then,它与then的不同点在于哪怕设置变量出现了异常也会被调用到。这个有点像java中的finally。

如果上面这个使用变量也要花费一段时间,那么可以考虑将其放入一个新的Future中:

future.then(...set an important variable...) .then((_) {new Future(() {...use the important variable...})});

使用一个新的Future可以给事件循环一个机会先去处理列队中的其他事件。

怎么安排一个任务
(责任编辑:ioter)

用户喜欢...

基于Spartan-6平台简单实现异步fifo与UART串口通信的联合使用

UART(即Universal Asynchronous Receiver Transmitter 通用异步收发器)是广泛使用的串行数据传输协议。UART允许在串行链路上进行全双工的通信。 串行外设用到RS232-C异步串行接口,一般采用专用的集成...


Vivado中异步FIFO的实现和使用

FIFO应用: 1、在千兆以太网数据写入,往DDR3里面写数据时候 2、AD采样时钟和内部时钟不同时,需要FIFO进行转换 3、同频异相时也需要用FIFO进行转换 Vivado中FIFO generator的配置方法 1、 2、stan...


嵌入式系统上的异步串口通信的实现

在嵌入式系统中,异步串口(UART)使用非常频繁,可以用于与各种外部系统(帧括PC)之间的通信。在硬件上UART通过在每个字节的传输中插入开始位和停止位,保证接收端可以正确地找到字...


异步fifo的设计(FPGA)

本文首先对异步 FIFO 设计的重点难点进行分析,最后给出详细代码。 一、FIFO简单讲解 FIFO的本质是RAM, 先进先出 重要参数:fifo深度(简单来说就是需要存多少个数据) fifo位宽(每个数据的...


FreeRTOS任务调度研究

这篇文章不介绍FreeRTOS移植,只是最近针对多核ARM Cortex系列平台做了移植后的一篇总结研究文章。所以不涉及对FreeRTOS整体的介绍,而只是分析任务调度这一块的机制。对应的Demo参考自CORTE...


变频调速时,变频器对异步电机有什么影响?

selina 在 周五, 09/22/2017 - 08:47 提交 变频调速时对电机产生的影响就是普通异步电机在非正弦波下的运行特性分析,因为变频调速不论采用什么样的控制方法其输出到电机端上的电压脉冲是非正...


老司机出品—疯狂造轮子之图片异步下载类

SDWebImage,我估计没有一个做iOS的不知道这个三方库吧,他为我们提供了简洁的图片异步下载方式。在他为我一句api带来这么大便利的同时,你有没有想过他是怎么实现的呢?让我们先来看看...


三相异步电动机常见故障分析与处理

三相异步电动机应用广泛,但通过长期运行后,会发生各种故障,及时判断故障原因,进行相应处理,是防止故障扩...


美国海军为水下机器人设计充电站 延长任务时间

随着自动科技的进展,各类型的无人机愈来愈普及,美国海军也全力研发,这些无人机器人的任务多半必须长期进行...


机器人总动员正在上演

2017世界机器人大会如约而至,北京地铁亦庄线荣昌东街站也迎来了客流高峰。就在这里,北京亦创国际会展中心集学...