我正在使用此代码测试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
来源:
#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
}
}
答案 0 :(得分:10)
问题是threadLoop
是一个成员函数,但是没有对象可以应用它。只是猜测:
std::thread connectionThread(&Connection::threadLoop, this);
但那只是句法问题;还有一个逻辑问题:该行创建了一个类型为std::thread
的本地对象,该函数在函数返回时消失。它的析构函数将调用std::terminate()
,因为该线程尚未加入。最有可能的是,这应该将一个线程附加到connectionThread
成员。要做到这一点:
std::thread thr(threadLoop, this);
std::swap(thr, connectionThread);
答案 1 :(得分:4)
您的代码有两个问题:
std::thread
构造函数std::thread
。对于第一个问题,作为Pete Becker suggests,您需要提供将调用该函数的对象,因为std::thread
的构造函数没有其他方法可以知道它。假设您要在正在构建的threadLoop()
对象上调用函数Connection
,可以执行以下操作:
//Launch thread
std::thread connectionThread(threadLoop, this);
在内部,构造函数将调用this->threadLoop()
(其中this
是它收到的Connection*
参数,当然不是std::thread
本身。你会没事的。
第二个问题是你的std::thread
在启动后立即被销毁,而没有将它加入主线程:这将调用terminate()
,这不是一件好事。 Pete再次提出了一个很好的选择。用以下代码替换上面的代码:
// Launch thread
std::thread thr(threadLoop, this);
std::swap(thr, connectionThread);
此代码之前的情况如下:
std::thread
对象,connectionThread
,它并不真正代表一个线程执行第一行代码后:
connectionThread
std::thread
对象thr
表示的实时线程,该线程将在Connection
构造函数的末尾销毁,从而导致调用terminate()
,因为它永远不会加入主线程。幸运的是,第二行代码可以解决问题。执行后:
std::thread
,thr
,它可以被安全地销毁,因为它不代表一个真正的线程(因此它不可连接)connectionThread
表示的实时线程,只要Connection
对象存在,该对象就不会被销毁。现在,问题是你希望在主线程被销毁之前加入connectionThread
,但你也想避免阻塞主线程。进行此连接的正确时间是最新的可能时间:connectionThread
即将被销毁。这发生在Connection
的析构函数中。所以我们将以这种方式为这个析构函数添加一行:
Connection::~Connection(){
mysqlConnection.disconnect();
connectionThread.join(); // Now connectionThread can be safely destroyed
}
此外,这是最安全的地方join()
,因为它可以确保您永远不会销毁未加入的connectionThread
。这是RAII的行动;如果您不熟悉RAII(或RIIA,有时称为)的概念,您可以在网络上找到有关这个非常重要概念的大量信息,包括本网站。
所有这些放在一起:创建一个Connection
对象将创建一个新线程;在这个线程中,将建立一个新的数据库连接并执行一个查询,而主线程保持空闲以用于任何其他用途(例如,管理GUI)。当Connection
对象最终被销毁时,主线程将等待额外的线程完成(如果需要),然后正常执行将继续。我希望这是你想用你的代码完成的。
答案 2 :(得分:2)
正如你可能从cppreference看到的那样,std::thread
的构造函数期望某种形式的函数;你可以通过std::bind
传递一个自由函数,一个静态成员函数或其中一个与其参数打包在一起的函数。为了执行非静态成员函数,您应该使用std::mem_fn
将它与应该调用的对象一起传递。