异步函数串行执行异常排查:isExecuting无法重置为false
问题:异步函数串行执行时锁变量无法重置为false
我希望串行执行异步函数,即等待前一个函数执行完毕后再启动下一个。为此,我创建了布尔变量isExecuting作为锁,用于阻塞直到可以执行下一个函数。但发现isExecuting被设为true后再也无法被设为false,请问原因是什么?
测试代码
test('Should execute serially', () async { WidgetsFlutterBinding.ensureInitialized(); final example = DoSynchronously(); example.convertToSync(); });
示例代码
class DoSynchronously { static bool isExecuting = false; static const readDelay = 1000; void convertToSync() { while (true) { waitToExecute(); isExecuting = true; anAsyncFunction(); } } void waitToExecute() { while (isExecuting) { print("read delay"); sleep( const Duration(milliseconds: readDelay), ); } } Future<void> anAsyncFunction() async { startExecuting(); await Future.delayed(Duration(seconds: 1), () => 'Delayed 2 seconds.') .then((result) => print(result)); stopExecuting(); } void startExecuting() { isExecuting = true; print("executing = true"); } void stopExecuting() { isExecuting = false; print("Stopped executing"); } }
问题原因
核心问题是同步阻塞代码彻底卡住了事件循环,导致异步函数的后续逻辑根本没机会执行:
convertToSync是同步的无限循环,调用waitToExecute时,里面的sleep是同步阻塞方法,会直接霸占当前线程,完全阻断事件循环。- 调用
anAsyncFunction()时,因为convertToSync没使用await等待它完成,函数刚执行到await就被挂起,主线程立刻回到循环里,再次调用waitToExecute。 - 此时
isExecuting已经被设为true,waitToExecute里的while+sleep会一直锁死主线程,事件循环无法处理Future.delayed完成后的回调,自然跑不到stopExecuting()来重置锁状态。
简单说:同步阻塞的代码把线程占死了,异步任务的收尾逻辑根本没机会运行。
正确的串行执行实现
要实现异步函数串行执行,得用异步循环+await等待任务完成,不能用同步阻塞的方式:
class DoSynchronously { static bool isExecuting = false; static const readDelay = 1000; // 改为异步函数 Future<void> convertToSync() async { while (true) { // 用异步等待替代同步阻塞,不卡事件循环 while (isExecuting) { print("read delay"); await Future.delayed(const Duration(milliseconds: readDelay)); } await anAsyncFunction(); // 等待上一个异步任务完全结束 } } Future<void> anAsyncFunction() async { isExecuting = true; print("executing = true"); await Future.delayed(Duration(seconds: 1), () => 'Delayed 2 seconds.') .then((result) => print(result)); isExecuting = false; print("Stopped executing"); } }
关键修改点:
- 把
convertToSync改成异步函数,用await等待每个anAsyncFunction执行完成,确保串行逻辑。 - 替换同步
sleep为异步Future.delayed,让事件循环能正常处理其他异步回调。 - 去掉冗余的
startExecuting/stopExecuting方法,直接在异步函数内维护锁状态,减少不必要的层级。
内容的提问来源于stack exchange,提问作者thebiggestlebowski
相关产品推荐
相关产品推荐

