Flutter开发·Dart中event loop任务队列工作原理

1,719 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

在Flutter开发中,Dart执行任务原则如同Android中的Handler一样,也是依靠事件驱动的。如图所示,当main方法执行后就生成了一个event loop时间循环,通过event loop不停的从时间队列中获取事件消息来完成程序中所有任务的执行。事件消息包括微任务队列microtask和事件队列event queue,其中microtask的优先级高于event queue,也就是说event loop每执行完毕一次事件后,都会再次查询事件队列中是否存在microtask任务,如果存在则优先执行,直到队列中不再存在microtask任务才会执行event queue任务,所以可以根据此特性在程序中对一个优先级高的任务做事件插队。

消息机制.png

下面用代码验证一下。上篇文章介绍了isolate中使用receivePort进行消息通信,这里receivePort的listen监听回调中的代码属于event queue任务,通过Future.microtask方法可以创建一个微任务队列。如控制台所示,当event loop中存在microtask时,它一定会优先执行,而并不是像代码所写的顺序那样按序执行。

void main(){
  ReceivePort receivePort = ReceivePort();

  receivePort.listen((message) {
    print(message);
  });

  Future.microtask((){
    print("这是微任务队列");
  });

  receivePort.sendPort.send("这是给event queue队列的消息");

  Future.microtask((){
    print("这是微任务队列2");
  });

  receivePort.sendPort.send("这是给event queue队列的消息2");

}

image.png

在上面的基础上,如果在某个微任务增加耗时操作,则后面的任务都会等待微任务结束后再执行,在如下代码中,在第一个微任务中sleep两秒后,后面的任务才得以执行。所以在使用时,即使要使用microtask插入一个优先级高的任务,也需要注意不要执行耗时较高的操作,这也正是单线程模型的特性。

2021-09-28 22.13.13.gif

总结

Dart事件队列循环包括两种队列:
  • 事件队列(event queue),包含所有的外来事件:I/O、mouse events、drawing events、timers、isolate之间的信息传递。
  • 微任务队列(microtask queue),表示一个短时间内就会完成的异步任务。它的优先级最高,高于event queue,只要队列中还有任务,就可以一直霸占着事件循环。microtask queue添加的任务主要是由 Dart内部产生。
事件循环原则
  • 优先执行任务队列中的微任务。
  • 即使当前队列中event queue任务数量再多,执行完一个任务后也会再次判断队列里是否包含微任务队列,如果有则执行,若没有则查询是否有event queue任务。