Dart事件循环机制

简介: Dart事件循环机制

什么是事件循环?

Dart 是单线程的,这意味着 Dart 代码是按照在 main出现的次序,一个接一个地执行的,不会被其他代码中断。

Dart 也支持异步,单线程和异步并不冲突。

为什么单线程也可以异步?这里有一个大前提,那就是我们的 App 绝大多数时间都在等待,而这些等待行为并不是阻塞的。

为什么单线程也可以异步?这里有一个大前提,那就是我们的 App 绝大多数时间都在等待,而这些等待行为并不是阻塞的。所以,基于这些特点,单线程模型可以在等待的过程中做别的事情,等真正需要响应结果了,再去做对应的处理,因为等待过程并不是阻塞的,所以给我们的感觉就像是同时在做多件事情一样,但其实始终只有一个线程在处理你的事情。等待这个行为是通过 Event Loop 驱动的。事件队列 Event Queue 会把其他平行世界完成的,需要主线程响应的事件放入其中。像其他语言一样,Dart 也有一个巨大的事件循环,在不断的轮循事件队列、取出事件(比如键盘事件、I\O 事件、网络事件等),在主线程同步执行其回调函数。


微任务队列

在 Dart 中,实际上有两个队列,一个是事件队列(Event Queue),另一个则是微任务队列(Microtask Queue)。

微任务队列,顾名思义,表示一个短时间内就会完成的异步任务。微任务队列在事件循环中的优先级是最高的,在每一次事件循环中,Dart 总是先去微任务队列中查询是否有可执行的任务,如果没有,才会处理后续的事件队列的流程

所以,Dart 中 Event Loop 完整版的流程图,应该如下所示:

一般的异步任务通常很少必须要在事件队列前完成,因此很少会使用微任务队列。Flutter 内部,也只有 7 处需要高优执行任务的场景用到了而已。而像 I/O、绘制、定时器这些异步事件,都是通过事件队列驱动主线程执行的。

事件队列包含外部事件,例如I/O, Timer,绘制事件,Future(部分情况)等等。

微任务队列则包含有Dart内部的微任务,主要是通过scheduleMicrotask,Future(部分情况)来调度。

事件与微任务队列

微任务与事件队列调用关系

void call() {
  Logger("start");
  Future(() => "Future").then((value) => Logger(value));
  scheduleMicrotask(() {
    Logger("microTask1");
    scheduleMicrotask(() {
      Logger("microTask2");
    });
  });
  Logger("end");
}
void Logger(Object obj) {
  print("${DateTime.now()} - $obj");
}

运行结果

flutter: 2023-03-20 17:10:28.289542 - start
flutter: 2023-03-20 17:10:28.297768 - end
flutter: 2023-03-20 17:10:28.369215 - microTask1
flutter: 2023-03-20 17:10:28.369964 - microTask2
flutter: 2023-03-20 17:10:28.376639 - Future

更复杂的情况

void call() {
  Logger("start");
  Future(() => "Future1").then((value) => Logger(value));
  scheduleMicrotask(() {
    Logger("microTask1");
    scheduleMicrotask(() {
      Logger("microTask2");
    });
  });
  Future(() => "Future2").then((value) => Logger(value));
  scheduleMicrotask(() {
    Logger("microTask3");
  });
  Logger("end");
}

运行结果

flutter: 2023-03-20 17:15:56.098555 - start
flutter: 2023-03-20 17:15:56.106995 - end
flutter: 2023-03-20 17:15:56.180110 - microTask1
flutter: 2023-03-20 17:15:56.180359 - microTask3
flutter: 2023-03-20 17:15:56.180983 - microTask2
flutter: 2023-03-20 17:15:56.187536 - Future1
flutter: 2023-03-20 17:15:56.188171 - Future2

符合上述预期的结果:Dart 总是先去微任务队列中查询是否有可执行的任务,如果没有,才会处理后续的事件队列的流程。配合使用async、await的情况

void call() async {
  Logger("start");
  Future(() => "Future1").then((value) => Logger(value));
  scheduleMicrotask(() {
    Logger("microTask1");
    scheduleMicrotask(() {
      Logger("microTask2");
    });
  });
  var v = await Future(() => "Future2");
  Logger(v);
  scheduleMicrotask(() {
    Logger("microTask3");
  });
  Logger("end");
}

运行结果

flutter: 2023-03-20 17:23:04.703378 - start
flutter: 2023-03-20 17:23:04.783701 - microTask1
flutter: 2023-03-20 17:23:04.784461 - microTask2
flutter: 2023-03-20 17:23:04.791345 - Future1
flutter: 2023-03-20 17:23:04.792122 - Future2
flutter: 2023-03-20 17:23:04.792347 - end
flutter: 2023-03-20 17:23:04.792815 - microTask3

后续结果会在await后执行;

相关文章
|
3月前
|
存储 JavaScript 前端开发
JavaScript:事件循环机制(EventLoop)
【9月更文挑战第6天】JavaScript:事件循环机制(EventLoop)
42 5
|
4月前
|
存储 前端开发 JavaScript
事件循环机制是什么
【8月更文挑战第3天】事件循环机制是什么
40 1
|
7月前
|
开发框架 JavaScript 前端开发
JavaScript的事件循环机制是其非阻塞I/O的关键
【5月更文挑战第13天】JavaScript的事件循环机制是其非阻塞I/O的关键,由调用栈、事件队列和Web APIs构成。当异步操作完成,回调函数进入事件队列,待调用栈空时,事件循环取队列中的任务执行。在游戏开发中,事件循环驱动游戏循环更新,包括输入处理、游戏逻辑更新和渲染。示例代码展示了如何模拟游戏循环,实际开发中则常使用游戏框架进行抽象处理。
100 4
|
7月前
|
前端开发 JavaScript UED
JavaScript 的事件循环机制是其非阻塞 I/O 模型的核心
【5月更文挑战第9天】JavaScript的事件循环机制是其非阻塞I/O的关键,通过单线程的调用栈和任务队列处理异步任务。当调用栈空时,事件循环从任务队列取出一个任务执行,形成循环。异步操作完成后,回调函数进入任务队列,等待被事件循环处理。微任务如Promise回调在每个宏任务结束后执行。此机制确保JavaScript能高效处理异步操作,不阻塞主线程,提供流畅的用户体验。
47 2
|
7月前
|
编解码 Dart UED
Flutter单线程异步及Isolate使用过程遇到的问题
Flutter单线程异步及Isolate使用过程遇到的问题 在Flutter中,所有的代码都运行在单线程中。这意味着如果我们的代码执行时间过长,就会导致UI线程卡顿,影响用户体验。因此,Flutter提供了一些异步机制来解决这个问题。
167 0
带你读《深入浅出Dart》十六、事件循环和协程机制(4)
带你读《深入浅出Dart》十六、事件循环和协程机制(4)
|
Dart JavaScript 前端开发
带你读《深入浅出Dart》十六、事件循环和协程机制(1)
带你读《深入浅出Dart》十六、事件循环和协程机制(1)
131 0
带你读《深入浅出Dart》十六、事件循环和协程机制(5)
带你读《深入浅出Dart》十六、事件循环和协程机制(5)
带你读《深入浅出Dart》十六、事件循环和协程机制(3)
带你读《深入浅出Dart》十六、事件循环和协程机制(3)
带你读《深入浅出Dart》十六、事件循环和协程机制(2)
带你读《深入浅出Dart》十六、事件循环和协程机制(2)