Rom*_*dgz 6 c++ c++11 stdthread
我正在用这段代码测试c ++ 11线程,但是在创建线程时,我遇到错误没有匹配函数来调用'std :: thread :: thread()'.
这就像我给std :: thread ctr的函数有问题,但我不知道它是怎么回事.它没有完成,但看起来对我来说:
标题:
#ifndef CONNECTION_H
#define CONNECTION_H
#include <thread>
#include <mysql++.h>
class Connection
{
public:
Connection(std::string mysqlUser, std::string mysqlPassword);
~Connection();
private:
std::string mysqlUser;
std::string mysqlPassword;
std::string mysqlIP;
int mysqlPort;
mysqlpp::Connection mysqlConnection;
std::thread connectionThread;
void threadLoop();
};
#endif // CONNECTION_H
Run Code Online (Sandbox Code Playgroud)
资源:
#include "connection.h"
Connection::Connection(std::string mysqlUser, std::string mysqlPassword)
{
this->mysqlUser = mysqlUser;
this->mysqlPassword = mysqlPassword;
this->mysqlIP = "localhost"; //default
this->mysqlPort = 3306; //default
//Launch thread
std::thread connectionThread(threadLoop);
}
Connection::~Connection(){
mysqlConnection.disconnect();
}
void Connection::threadLoop(){
//Connect to mySQL database
mysqlConnection = new mysqlpp::Connection(false);
if(mysqlConnection.connect(NULL, mysqlIP.c_str(), mysqlUser.c_str(), mysqlPassword.c_str(), mysqlPort)){
std::string consulta = "SELECT * FROM 'Coordinates'";
mysqlpp::Query query = mysqlConnection.query(consulta);
mysqlpp::StoreQueryResult res = query.store();
query.reset();
}
while(true){
// Stuff
}
}
Run Code Online (Sandbox Code Playgroud)
Pet*_*ker 10
问题是它threadLoop是一个成员函数,但没有对象可供应用.只是猜测:
std::thread connectionThread(&Connection::threadLoop, this);
Run Code Online (Sandbox Code Playgroud)
但那只是句法问题; 还有一个逻辑问题:该行创建了一个类型的本地对象,std::thread当函数返回时它会消失.它的析构函数将调用,std::terminate()因为该线程尚未连接.最有可能的是,这应该是一个线程附加到connectionThread成员.要做到这一点:
std::thread thr(threadLoop, this);
std::swap(thr, connectionThread);
Run Code Online (Sandbox Code Playgroud)
您的代码有两个问题:
std::thread构造函数提供不完整的信息std::thread前一个与主线程连接。对于第一个问题,正如Pete Becker所建议的那样,您需要提供将在其上调用函数的对象,因为for的构造函数std::thread没有其他方法可以知道它。假设要threadLoop()在Connection正在构造的对象上调用函数,可以执行以下操作:
//Launch thread
std::thread connectionThread(threadLoop, this);
Run Code Online (Sandbox Code Playgroud)
在内部,构造函数将调用this->threadLoop()(当然,它接收到this的Connection*参数在哪里,而不是std::thread自身)。而且您会没事的。
第二个问题是your std::thread在启动后立即被销毁,而没有将其加入主线程:这将调用terminate(),这不是一件好事。皮特再次提出了一个很好的选择。将上面的代码替换为:
// Launch thread
std::thread thr(threadLoop, this);
std::swap(thr, connectionThread);
Run Code Online (Sandbox Code Playgroud)
此代码之前的情况如下:
std::thread对象,connectionThread它实际上并不代表线程执行第一行代码后:
connectionThreadstd::threadobject 表示的活动线程,该线程thr将在Connection构造函数的末尾被销毁,从而导致调用,terminate()因为它从未连接到主线程。幸运的是,第二行代码可以解决。执行后:
std::thread,thr可以安全地销毁它,因为它不代表真正的线程(因此它不可联接)connectionThread,该对象只要Connection存在就不会被破坏。现在,问题在于您想connectionThread在销毁主线程之前加入它,但同时也要避免阻塞主线程。进行此连接的正确时间是最新的时间:connectionThread即将销毁的时间。这发生在的析构函数上Connection。因此,我们将通过以下方式向此析构函数添加一行:
Connection::~Connection(){
mysqlConnection.disconnect();
connectionThread.join(); // Now connectionThread can be safely destroyed
}
Run Code Online (Sandbox Code Playgroud)
此外,这是最安全的通话位置join(),因为它可以确保您永远不会销毁未连接的connectionThread。这是行动中的RAII;如果您不熟悉RAII(或RIIA,有时也称为RIIA)的概念,则可以在Web站点(包括该站点)中找到许多有关此非常重要的概念的信息。
所有这些放在一起:创建Connection对象将创建一个新线程;在该线程中,将建立一个新的数据库连接并执行查询,而主线程则可用于其他用途(例如,管理GUI)。当Connection对象最终被销毁时,主线程将等待附加线程完成(如有必要),然后正常执行将继续。我希望这是您想要用代码完成的工作。