C++ 在类中的成员更改时终止线程中的循环

C++ 在类中的成员更改时终止线程中的循环,c++,multithreading,C++,Multithreading,我有一个类在一个单独的线程上运行一个循环,当我将一个成员的值更改为false时,我希望它中断: #include <iostream> #include <thread> #include <future> #include <chrono> #include <functional> #include <atomic> class A { public: void ChangeLoop(){ lo

我有一个类在一个单独的线程上运行一个循环,当我将一个成员的值更改为false时,我希望它中断:

#include <iostream>
#include <thread>
#include <future>
#include <chrono>
#include <functional>
#include <atomic>

class A
{
public:
    void ChangeLoop(){
        loop = !loop;
            if(loop){
                std::future<void> fi = std::async(std::launch::async, &A::RunLoop, this, std::ref(loop));
            }
    }
    void RunLoop(std::atomic<bool> &loop_ref){

        while(loop_ref){
            emit(loop_ref);
            std::this_thread::sleep_for(std::chrono::milliseconds(50));
        }
    }

private:
    std::atomic<bool> loop {false};
    std::mutex emit_mutex;
    template<class...Ts> void emit(Ts&&...ts){
        auto lock = std::unique_lock<std::mutex>(emit_mutex);
        using expand = int[];
        void(expand{
            0,
            ((std::cout << ts << "\n"), 0)...
        });
    }
};


int main(){
    A a;
    a.ChangeLoop();
    std::this_thread::sleep_for(std::chrono::seconds(2));
    a.ChangeLoop();
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
甲级
{
公众:
void ChangeLoop(){
循环=!循环;
如果(循环){
std::future fi=std::async(std::launch::async,&A::RunLoop,this,std::ref(loop));
}
}
void RunLoop(标准::原子循环和循环参考){
while(循环参考){
发射(环路参考);
std::this_线程::sleep_for(std::chrono::毫秒(50));
}
}
私人:
std::原子循环{false};
std::互斥体发出互斥体;
模板无效发射(Ts&…Ts){
自动锁定=标准::唯一锁定(发出互斥);
使用expand=int[];
空(展开){
0,

((std::cout既然您已经找到了问题的有效解决方案,我只想指出为什么
std::async
不是正确的选择

从网上参考:

如果从std::async获取的std::future未从引用中移动或绑定到引用,则std::future的析构函数将在完整表达式的末尾阻塞,直到异步操作完成。

因此,这里有
std::future
阻塞的析构函数,因为
RunLoop
线程由于其
while
循环而从未完成执行

即使
std::async
中的返回值在
ChangeLoop
中被忽略,并且没有分配给
std::future
时,这也是正确的

<有些C++专家说,<代码> STD:由<代码> STD::AcYNC/<代码>产生的未来< /代码>不应该阻止。这是萨特的一个例子。
但是现在,评论中提出的解决方案(使用
std::detach
)是正确的选择。

std::async
在这里是错误的选择。将
std::thread
detach()
结合使用。更改
std::future fi=std::async(std::launch::async,&A::RunLoop,this,std::ref(loop));
to
std::thread(&A::RunLoop,this,std::ref(loop)).detach()我希望你得到的点<代码> > STD::AsYNC/<代码>不是正确的选择。谢谢@ OZ17,这对我起了作用!谢谢@ P.W.在阅读了你提供的信息并在C++线程上观看Bo Qian的视频之后,我明白了为什么我需要使用STD::线程带DATAT。在这种情况下,我们将使用ch。
#include <iostream>
#include <thread>
#include <future>
#include <chrono>
#include <functional>
#include <atomic>

class A
{
public:
    void ChangeLoop(){
        loop = !loop;
            if(loop){
                std::future<void> fi = std::async(std::launch::async, &A::RunLoop, this);
            }
    }
    void RunLoop(){
        while(loop){
            emit(loop);
            std::this_thread::sleep_for(std::chrono::milliseconds(50));
        }
    }

private:
    std::atomic<bool> loop {false};
    std::mutex emit_mutex;
    template<class...Ts> void emit(Ts&&...ts){
        auto lock = std::unique_lock<std::mutex>(emit_mutex);
        using expand = int[];
        void(expand{
            0,
            ((std::cout << ts << "\n"), 0)...
        });
    }
};


int main(){
    A a;
    a.ChangeLoop();
    std::this_thread::sleep_for(std::chrono::seconds(2));
    a.ChangeLoop();
    return 0;
}