15

如何停止/取消使用std::async和策略创建的异步任务std::launch::async?换句话说,我已经使用未来对象启动了在另一个线程上运行的任务。有没有办法取消或停止正在运行的任务?

4

3 回答 3

28

简而言之,没有。

更长的解释:在标准 C++ 中没有取消任何线程的安全方法。这将需要取消线程。这个特性在 C++11 标准化过程中已经讨论过很多次,普遍的共识是没有安全的方法可以这样做。据我所知,在 C++ 中进行线程取消的主要考虑方法有三种。

  1. 中止线程。这更像是一个紧急停止。不幸的是,它不会导致堆栈展开或调用析构函数。线程可能处于任何状态,因此可能持有互斥锁,堆分配的数据将被泄露,等等。这显然永远不会被考虑太久,因为它会使整个程序未定义。如果您想自己执行此操作,则只需使用native_handle即可。然而,它将是不可移植的。

  2. 强制取消/中断点。当请求线程取消时,它会在内部设置一些变量,以便下次调用任何预定义的中断点集(例如睡眠、等待等)时,它会抛出一些异常。这将导致堆栈展开并且可以进行清理。不幸的是,这种类型的系统很难让任何代码异常安全,因为大多数多线程代码会突然抛出。这是boost.thread使用的模型。它用于disable_interruption解决一些问题,但除了最简单的情况外,要解决任何问题仍然非常困难。Boost.thread使用这个模型,但它一直被认为是有风险的,可以理解的是,它没有与其他模型一起被接受到标准中。

  3. 自愿取消/中断点。最终,这归结为在您需要时自己检查某些条件,并在适当的情况下以受控方式自行退出线程。我隐约记得一些关于添加一些库功能来帮助解决这个问题的讨论,但从未达成一致。

我只会使用 3 的变体。例如,如果您使用的是 lambda,那么很容易引用一个可以不时检查的原子“取消”变量。

于 2012-12-04T01:45:34.267 回答
4

在 C++11 中(我认为)没有取消线程的标准方法。如果你得到 std::thread::native_handle(),你可以用它做一些事情,但这不是可移植的。

于 2012-12-03T21:22:07.983 回答
-1

也许你可以通过检查一些条件来这样做:

class Timer{
public:
    Timer():timer_destory(false){}
    ~Timer(){
        timer_destory=true;
        for(auto result:async_result){
            result.get();
        }
    }
    int register_event(){
        async_result.push_back(
            std::async(std::launch::async,[](std::atomic<bool>& timer_destory){
                while(!timer_destory){
                //do something
                }
            },std::ref(timer_destory))
            );
    }
private:
    std::vector<std::future<int>> async_result;
    std::atomic<bool> timer_destory;
}
于 2016-04-12T11:32:56.450 回答