Dart汇总请点击这里
本文讲述了Dart事件循环的原理,
当你要在Dart中使用异步模型请参考:Dart 异步模型
当你要在Dart中控制任务调度请参考:Dart 任务调度
文章目录
-
-
- 概述
-
- 基础概念之消息循环和消息队列
- Dart的单线程执行
- Dart的消息循环和消息队列
- 怎么安排一个任务
- 总结
-
概述
异步任务在Dart中随处可见,例如许多库的方法调用都会返回Future对象来实现异步处理,我们也可以注册Handler来响应一些事件,如:鼠标点击事件,I/O流结束和定时器到期。
Dart 是事件驱动的体系结构,该结构基于具有单个事件循环和两个队列的单线程执行模型。 Dart虽然提供调用堆栈。 但是它使用事件在生产者和消费者之间传输上下文。 事件循环由单个线程支持,因此根本不需要同步和锁定。
划重点:
单线程执行
两个队列
- MicroTask queue 微任务队列
- Event queue 事件队列
基础概念之消息循环和消息队列
一个消息循环的职责就是不断从消息队列中取出消息并处理他们直到消息队列为空。
消息队列中的消息可能来自用户输入,文件I/O消息,定时器等。例如下图的消息队列就包含了定时器消息和用户输入消息。
Dart的单线程执行
当一个Dart的方法开始执行时,他会一直执行直至达到这个方法的退出点。换句话说Dart的方法是不会被其他Dart代码打断的。
Note:一个Dart的命令行应用可以通过创建isolates来达到并行运行的目的。isolates之间不会共享内存,它们就像几个运行在不同进程中的app,中能通过传递message来进行交流。出了明确指出运行在额外的isolates或者workers中的代码外,所有的应用代码都是运行在应用的main isolate中。要了解更多相关内容,可以查看https://www.dartlang.org/articles/event-loop/#use-isolates-or-workers-if-necessary
如下图所示,当一个Dart应用开始的标志是它的main isolate执行了main方法。当main方法退出后,main isolate的线程就会去逐一处理消息队列中的消息。
事实上,上图是经过简化的流程。
Dart的消息循环和消息队列
一个Dart应用有一个消息循环和两个消息队列
-
MicroTask queue 微任务队列 只包含来自当前isolate的内部代码。
-
Event queue 事件队列 包含所有外来的事件 I/O,mouse events,drawing events,timers,isolate之间的message等
Dart事件循环执行如上图所示
- Dart的入口是main函数,所以main函数中的代码会优先执行;
- main函数执行完后,会启动一个事件循环Event Loop,并开始执行队列中的任务;
- 按照FIFO的顺序,执行Microtask Queue中的所有任务;
- 当微任务队列中任务为空时,执行Event Queue中的第一个任务;
- 当Event Queue第一个任务执行完之后 ,开始执行循环:执行所有 microtask,接着执行 event queue 中第一个事件。
注意:我们可以看出,将任务加入到MicroTask中可以被尽快执行,但也需要注意,当事件循环在处理MicroTask队列时,Event队列会被卡住,应用程序无法处理鼠标单击、I/O消息等等事件。
注意:虽然你可以预测任务执行的顺序,但你无法准确的预测到事件循环何时会处理你期望的任务。例如当你创建一个延时1s的任务,但在排在你之前的任务结束前事件循环是不会处理这个延时任务的,也就是或任务执行可能是大于1s的。
怎么安排一个任务
当你需要指定一些代码稍后运行的时候,请参考:Dart 任务调度
总结
以下有几点关于dart的事件循环机制需要牢记于心:
- Dart事件循环执行两个队列里的事件:event队列和microtask队列。
event队列的事件来自dart(future,timer,isolate message等)和系统(用户输入,I/O等)。 - 目前为止,microtask队列的事件只来自dart。
- 事件循环会优先清空microtask队列,然后才会去处理event队列。
- 当两个队列都清空后,dart就会退出。
- main方法,来自event队列和microtask队列的所有事件都运行在Dart的main isolate中。
当你要安排一个任务时,请遵守以下规则:
- 如果可以,尽量将任务放入event队列中。
- 使用Future的then方法或whenComplete方法来指定任务顺序。
- 为了保持你app的可响应性,尽量不要将大计算量的任务放入这两个队列。
- 大计算量的任务放入额外的isolate中。