You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CancelableOperation调用cancel后_trytest()仍执行完毕的问题

解决CancelableOperation无法取消_trytest()方法的问题

问题现象

用async: ^2.9.0库的CancelableOperation想取消_trytest()方法,但点击Cancel按钮后,_trytest()还是会完整执行,控制台输出:

flutter: on _trytest
flutter: onCancel
flutter: Completed

相关代码如下:

变量声明

CancelableOperation<void> cancellableOperation =
    CancelableOperation.fromFuture(
  Future.value('future result'),
  onCancel: () {},
);

UI部分代码

_isloading
    ? Column(
        children: [
          Center(
            child: CircularProgressIndicator(),
          ),
          ElevatedButton(
            child: Text('Cancel'),
            onPressed: () {
              cancellableOperation.cancel();
            },
          ),
        ],
      )
    : ElevatedButton(
        child: Text('Delete Account'),
        onPressed: () {
          setState(() {
            _isloading = true;
          });

          cancellableOperation = CancelableOperation.fromFuture(
              _trytest(),
              onCancel: () => {
                    debugPrint('onCancel'),
                    
                    cancellableOperation.cancel(),
                    setState(() {
                      _isloading = false;
                    })
                  });
        },
      ),

_trytest()方法

Future<void> _trytest() async {
  print('on _trytest');
  await Future.delayed(Duration(seconds: 4)).then((value) => {
        print("Completed"),
        setState(() {
          _isloading = false;
        })
      });
}

问题原因

CancelableOperation.fromFuture()只是包装现有Future,但没法中断已经启动的异步任务。_trytest()里的Future.delayed一旦开始执行就会跑完,Cancel操作只会触发onCancel回调,不会终止内部的异步逻辑。

解决方案

要真正取消任务,得在_trytest()内部监听取消状态,主动终止后续执行。以下是两种可行的修改方式:

方式一:在_trytest()内部检查取消状态

  1. 修改_trytest()方法,接收CancelableOperation参数并判断取消状态:
Future<void> _trytest(CancelableOperation<void> operation) async {
  print('on _trytest');
  await Future.delayed(Duration(seconds: 4)).then((value) {
    // 先判断是否取消,再执行后续逻辑
    if (!operation.isCanceled) {
      print("Completed");
      setState(() {
        _isloading = false;
      });
    }
  });
}
  1. 更新UI中创建CancelableOperation的代码,把当前实例传入_trytest():
cancellableOperation = CancelableOperation.fromFuture(
  _trytest(cancellableOperation),
  onCancel: () {
    debugPrint('onCancel');
    setState(() {
      _isloading = false;
    });
  },
);

方式二:用CancelableOperation的then回调处理完成逻辑

  1. 简化_trytest()方法:
Future<void> _trytest() async {
  print('on _trytest');
  await Future.delayed(Duration(seconds: 4));
}
  1. 修改UI的点击事件,在CancelableOperation的then回调中判断取消状态:
onPressed: () {
  setState(() {
    _isloading = true;
  });

  cancellableOperation = CancelableOperation.fromFuture(
    _trytest(),
    onCancel: () {
      debugPrint('onCancel');
      setState(() {
        _isloading = false;
      });
    },
  );

  // 仅当未取消时执行完成逻辑
  cancellableOperation.then((_) {
    if (!cancellableOperation.isCanceled) {
      print("Completed");
      setState(() {
        _isloading = false;
      });
    }
  });
}

关键说明

  • CancelableOperation的作用是管理取消回调、阻止后续then/whenComplete等回调执行,但没法直接中断已启动的异步操作。
  • 必须在异步任务的关键节点主动检查取消状态,放弃后续逻辑,才能实现真正的“取消”效果。

内容的提问来源于stack exchange,提问作者ismail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 15:00:53