Dart异步编程async方法未按预期异步执行问题咨询
底层运行逻辑
Dart采用单线程Isolate执行模型,默认所有代码都在主Isolate的执行栈中顺序执行,核心规则如下:
async函数并不会默认将所有逻辑丢到异步队列,仅当执行到函数内第一个await表达式时,才会暂停当前函数执行,将await后续的逻辑注册为异步回调,同时将执行权交回给调用方,继续执行调用方后续的同步代码。
两段代码的执行差异点:
- 第一段代码中
dataProcessAsync执行到await Future.delayed(Duration(seconds: 2))时触发了await逻辑,执行权交回main函数,先执行后续的print("Process 3")、print("Process 4"),等延迟结束后再执行await后的print语句,因此输出顺序符合异步预期。 - 第二段代码中
dataProcessAsync全程没有await表达式,整个函数体的for循环、print语句都属于同步执行逻辑,调用dataProcessAsync()时会直接跑完整个函数的所有代码,才会回到main函数执行后续的打印语句,因此出现阻塞。
解决方案
根据计算任务的重量可以选择两种方案:
轻量计算任务:主动将计算逻辑包裹到Future回调中,触发await让出执行权
代码示例:Future<void> dataProcessAsync() async { // 包裹到Future回调中,遇到await主动让出线程 await Future(() { for(int i = 1; i <= 10000000000; i++){} }); print("Process Completed!"); }修改后调用该函数时,执行到await就会把Future回调丢到事件队列,先执行main函数后续的打印逻辑,等主Isolate空闲后再执行队列中的for循环逻辑。
重度CPU密集型计算任务:新开独立Isolate执行计算,完全不占用主Isolate资源
上述轻量方案的计算逻辑还是在主Isolate执行,计算过程中依然会阻塞UI渲染、事件响应等主Isolate的其他任务,这种场景下需要用独立Isolate处理:
代码示例:import 'dart:isolate'; // 独立Isolate执行的计算逻辑 void heavyCalculation(SendPort sendPort) { for(int i = 1; i <= 10000000000; i++){} sendPort.send("Process Completed!"); } Future<void> dataProcessAsync() async { final receivePort = ReceivePort(); // 启动新Isolate执行计算 await Isolate.spawn(heavyCalculation, receivePort.sendPort); // 监听计算结果 final result = await receivePort.first; print(result); receivePort.close(); }
内容的提问来源于stack exchange,提问作者NICLOS CANOZALES
相关产品推荐
相关产品推荐

