2016-12-31 16 views
0

这里是什么,我试图做一个简化版本:创建一个类来存储线程,并美其名曰

#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; 
} 

(注:代码已经改变,因为问题是书面)

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

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

+0

你在运行这个吗?使用GCC,我甚至无法编译程序,它抱怨将'this-> main'和'this-> render'传递给''thread'构造函数,因为*“非法使用非静态成员函数”*。 – Dolda2000

+0

@ Dolda2000 MinGW-W64-builds-4.3.0 – Brandon

回答

4

这里的问题是,你不要等待线程结束。在main中,您创建了c。然后这会产生线程。接下来发生的事情是返回销毁c。当c被销毁时,它会破坏其成员。现在,当如果它没有被加入或脱离一个线程被摧毁然后std::terminate被称为程序结束

你需要做的是在析构函数,设置runningfalse然后调用两个线程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)); 
+0

我已经更新了相应的代码,所有东西都像魅力一样,但占位符变量'running'实际上是一个由函数返回的布尔值。我将如何去确保这是线程安全的? – Brandon

相关问题