There is a member function which runs asynchronously using std::future and std::async . In some case, I need to cancel it. (The function loads near objects consecutively and sometimes an objects gets out of range while loading it.) I already read the answers to this question解决了相同的问题,但是我无法使它正常工作。

这是简化的代码,其结构与我的实际程序相同。在异步运行时调用Start()Kill()会导致崩溃,因为input的访问冲突。

在我看来,代码应按以下方式工作。调用Kill()时,将禁用运行标志。下一个命令get()应该等待线程结束,因为它检查了运行标志,所以它很快就会执行。取消线程后,删除input指针。

#include <vector>
#include <future>
using namespace std;

class Class
{
    future<void> task;
    bool running;
    int *input;
    vector<int> output;

    void Function()
    {
        for(int i = 0; i < *input; ++i)
        {
            if(!running) return;
            output.push_back(i);
        }
    }

    void Start()
    {
        input = new int(42534);
        running = true;
        task = async(launch::async, &Class::Function, this);
    }

    void Kill()
    {
        running = false;
        task.get();
        delete input;
    }
};

似乎该线程没有注意到将运行标志切换为false。我怎么了

最佳答案

由于没有人真正回答过这个问题,所以我会这样做。

running变量的写入和读取不是原子操作,因此代码中没有任何东西会导致两个线程之间的任何同步,因此也无法确保异步线程看到该变量已更改。

一种可能的发生方式是,编译器分析Function的代码,确定该线程中对该变量不进行任何写操作,并且由于它不是原子对象,因此不需要其他线程进行写操作,因此它是将代码重新排列为完全合法:

void Function()
{
    if(!running) return;
    for(int i = 0; i < *input; ++i)
    {
        output.push_back(i);
    }
}

显然,在此代码中,如果running在函数启动后发生更改,则不会导致循环停止。

C++标准允许您通过两种方式同步两个线程,要么使用互斥锁,仅在互斥锁锁定时读取或写入running变量,或者使该变量成为原子变量。在您的情况下,将runningbool更改为atomic<bool>将确保对变量的写入与对变量的读取同步,并且异步线程将终止。

关于c++ - 如何取消std::async函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14304299/

10-13 08:02