创建一个类来存储线程并调用它们

时间:2016-12-31 00:00:27

标签: c++ multithreading c++11

以下是我要做的简化版本:

#include <iostream>
#include <vector>
#include <thread>
#include <atomic>

class client {
private:
    std::vector<std::thread> threads;
    std::atomic<bool> running;

    void main() {
        while(running) {
            std::cout << "main" << std::endl;
        }
    }

    void render() {
        while(running) {
            std::cout << "render" << std::endl;
        }
    }
public:
    client() {
        running = true;

        threads.push_back(std::thread(&client::main, this));
        threads.push_back(std::thread(&client::render, this));
    }

    ~client() {
        running = false;
        for(auto& th : threads) th.join();
    };
};

int main() {
    client c;

    std::string inputString;
    getline(std::cin, inputString);

    return 0;
}

(注意:自编写问题以来代码已经更改)

我要做的是创建一个包含主循环(类),渲染和其他一些东西的线程的类。但是我无法使用这个简化版本。我曾尝试使用互斥锁来锁定和解锁线程,但似乎没有任何帮助。我不知道它为什么不起作用,但我怀疑这是this中使用threads.push_back(std::thread(this->main, this));的结果。

代码的当前结构不必保留......唯一的要求是使用它自己的成员函数中的一个作为线程(并且该线程存储在类中)。我不确定这是否需要两个课程,或者我在一个课程中尝试这样做是否正确。我已经看到很多创建对象的示例,然后调用创建线程的成员。我试图避免这种情况,而是在构造函数中创建线程。

1 个答案:

答案 0 :(得分:4)

这里的问题是你不要等待线程结束。在main中,您可以创建c。然后产生线程。接下来要做的就是返回破坏c的东西。当c被摧毁时,它会摧毁其成员。现在,如果一个线程在没有加入或分离的情况下被销毁,那么调用std::terminate并且程序结束

您需要做的是在析构函数中,将running设置为false,然后在两个线程上调用join。这将停止每个线程中的循环并允许c正确销毁。

这样做会带来另一个问题。 running不是原子变量,因此在线程读取它时写入它是未定义的行为。我们可以通过将运行更改为提供同步的std::atomic<bool>来完成此操作。

我还必须对线程构造进行更改。如果要使用成员函数,则语法应为

std::thread(&class_name::function_name, pointer_to_instance_of_class_name, function_parameters)

所以在这种情况下它将是

threads.push_back(std::thread(&client::main, this));
threads.push_back(std::thread(&client::render, this));