在c++ (cpp)中,在类中创建一个线程并让它在类中的函数上执行
making a thread within a class and having it execute on a funtion within the class in c++ (cpp)
我想做一个程序,其中有多个线程,线程之间的唯一交互应该是创建几个变量,仅用于在线程之间传输。其中一个是队列。我想让一个线程不断地写文件,我想让其他线程不断地给它写行。
但是为了简单起见,我想通过创建类然后简单地从该类调用一个名为give_line()的函数来实现这一切。我想要的线程是写的文件私有,这样别人就不能乱搞它。
class bar
{
private:
std::queue<std::string> lines; // The queue
void write() // The function we call from thread
{
std::cout << "Hello world from other thread";
}
public:
bar() // constructor
{
std::thread writer(&bar::write, this); // thread
}
}
int main()
{
bar testing;
std::cout << "Hello World from main thread" << std::endl;
/*
What this does is it allows me to keep the console open till we get a enter key.
*/
std::cin.clear();
std::cin.ignore(32767, 'n');
std::cin.get();
return 0;
}
.
output:
Hello world from other thread
为什么这没有意义,为什么它不起作用,我不明白。它启动了,然后突然崩溃了。我想不明白。当我在一个类中没有它时,它就会起作用,但是其他人可以扰乱线程,我真的不想这样。除非我需要,否则我不会给出太多项目代码。我创建这个类以及其他函数和变量的原因是你们不需要知道的。
我知道我需要一个writer.join()。但那是以后的事了。我想要另一个变量能够一次结束一切。这个变量只能从主线程访问,所以其他线程不能干扰它。有点像kill_all变量。
这里有多个问题,但首先也是最重要的是std::thread
的构造函数在新启动的线程中执行函数。看起来你不是在传递一个函数,而是在传递一个类方法。
我相当确定,当你的编译器试图编译这段代码时,它对你大喊大叫。仅仅因为你的编译器选择生成某种编译的目标文件,尽管它报告了错误,并不意味着编译器的诊断可以被忽略。
你可能想做这样的事情:
static void invoke_write(bar *p)
{
p->write();
}
bar()
{
std::thread writer(&invoke_write, this);
}
现在,您正在调用一个静态函数,并向它传递一个指向实例化类的指针,它使用该指针调用类方法。
但是你崩溃的真正原因是因为你在bar
的构造函数范围内实例化了std::thread
的实例。
当bar
的构造函数返回时,std::thread
对象,就像任何其他函数/方法作用域对象一样,被销毁,调用它的析构函数。但是,您刚刚启动了正在运行的线程,如果在线程仍在运行时调用std::thread
的析构函数,则会调用terminate()
,从而终止程序。
如果线程正在运行,必须在销毁std::thread
实例之前执行join()
。所以,要么像这样:
bar()
{
std::thread writer(&invoke_write, this);
writer.join();
}
或者,使std::thread
的实例成为类成员,在构造函数中实例化它,并在析构函数中加入它。比如:
bar() : writer(&invoke_write, this)
{
}
~bar()
{
writer.join();
}
private:
std::thread writer;
当然,哪种方法是正确的取决于您的应用程序的需求。
对您的类进行一个简单的更改,与@Sam Varchavchik一致,是为了确保在创建线程对象后不会立即丢失线程对象。
class bar
{
private:
std::queue<std::string> lines; // The queue
std::thread writer;
void write() // The function we call from thread
{
std::cout << "Hello world from other thread";
}
public:
bar() : writer{&bar::write, this} {}
~bar()
{
writer.join();
}
};
这里,写线程在构造函数中初始化,在析构函数中等待它完成。
您可以在这里看到稍微修改过的代码运行:http://ideone.com/Xf4dw5
正如Sam所提到的,在旧的c++中,不能仅仅通过传递类方法来创建线程,因为它也需要有对象。现代c++通过将两者绑定在一起来实现这一点,就像你通过将'this'传递给线程构造函数所做的那样。
- 执行函数时导致崩溃的变量
- 在多个时间戳处执行函数
- 程序不会执行函数 c++
- 仅在函数模板中为那些定义了函数的类型执行函数
- 如何在 c++ 的类声明中执行函数?
- 从 std::vector 迭代器中执行函数指针
- 异步 60 秒延迟后C++执行函数?
- 如果发生错误,则返回错误值,否则,继续执行函数
- 执行函数两次
- C++11:如何在 n 秒后在主线程中执行函数
- C++执行函数和 lambda 内部
- 从主线程C 11执行函数调用的线程
- 现代C++执行函数返回指针的方法
- 为什么Win API线程执行函数,而标准线程则没有
- varargs宏以执行函数调用或将其转换为字符串
- 单步执行函数,但不进入VS2017的参数评估
- 加载 Lua 文件并使用变量而不执行函数
- 尽可能在编译时执行函数契约
- 在QT应用程序中创建并执行函数
- 如何使用boostsio_service.post()执行函数并使用数组或指针作为参数