2016-06-02 3 views
0

У меня есть два подключения базы данных QSqlDatabase, «local» и «remote». У меня есть функция, которая использует оба соединения (получить данные из локальной базы данных и отправить на удаленный db). Когда я запускаю эту функцию из своего класса QThread, локальное соединение работает (у меня есть ожидаемые данные), но удаленное соединение терпит неудачу. Но если я запустил эту функцию вне класса QThread (в main()), оба соединения работают.QSqlDatabase: невозможно использовать соединение из QThread

Удаленное подключение не работает, когда я пытаюсь открыть соединение с сообщением об ошибке: «QSqlDatabasePrivate :: database: невозможно открыть базу данных: QMYSQL: невозможно подключиться». До этого я тестировал, было ли соединение действительным (isValid()), и оно было okey. Я также проверяю, было ли соединение уже открыто, но это не так.

Я также нашел эту информацию, но так как «местное» соединение работает с резьбой, это не может быть вопросом:

Потоки и модуль SQL соединение может использоваться только в пределах который создал его. Перемещение соединений между потоками или создание запросов из другого потока не поддерживается. http://doc.qt.io/qt-5/threads-modules.html#threads-and-the-sql-module

Ошибка найдена в Qt 5.5.1, 32bit, Ubuntu 14.04. Также тестировали на малине Pi, Qt 5.6, но с результатом «Ошибка сегментации».

Что не так?

main.c

main() 
{ 
    DataHandler dh(); 
    DataHandlerThread dht(&dh); //pointer to dh to get access to dh functions from the thread 

    //here I run dh.foo() or dht.run(), never both functions 
    dh.foo(); 
    dht.run(); 
    ... 
} 

datahandler.cpp

DataHandler::DataHandler() 
{ 
    m_dbLocal = QSqlDatabase::addDatabase("QMYSQL", "local"); 
    m_dbLocal.setHostName("localhost"); 
    ... 

    m_dbRemote = QSqlDatabase::addDatabase("QMYSQL", "remote"); 
    m_dbRemote.setHostName(...); 
    ... 
} 

DataHandler::foo() 
{ 
    qDebug() << QSqlDatabase::connectionNames(); //always ("remote", "local") 
    m_dbLocal.isValid(); //always true 
    m_dbLocal.open(); //always true 

    m_dbRemote.isValid(); //always true 

    //true if foo() is called from main using dm.foo() 
    //QSqlDatabasePrivate::database: unable to open database: " QMYSQL: Unable to connect" if called from main using dmt.run() 
    m_dbRemote.open(); 
} 

datahandlerthread.h

class DataHandlerThread : public QThread 
{ 
    Q_OBJECT 
public: 
    explicit DataHandlerThread(DataHandler* dh); 

private: 
    void run() Q_DECL_OVERRIDE; 

    DataHandler* m_dh; 

}; 

datahandlerthread.cpp

DataHandlerThread::DataHandlerThread(DataHandler* dh) 
{ 
    m_dh = dh; 
} 

void DataHandlerThread::run() 
{ 
    m_dh->foo(); 
} 
+0

Возможно, при размещении кода может возникнуть проблема? – Silicomancer

+0

Сообщение обновлено с кодом – Peder

ответ

0

Я нашел решение этой проблемы. Решение заключается в создании новых экземпляров и локального и удаленного подключения в конструкторе DataHandlerThread:

datahandlerthread.cpp

DataHandlerThread::DataHandlerThread(DataHandler* dh) 
{ 
    m_dh = dh; 
    m_dbLocal = QSqlDatabase::addDatabase("QMYSQL", "local_thread"); 
    m_dbLocal.setHostName("localhost"); 
    ... 

    m_dbRemote = QSqlDatabase::addDatabase("QMYSQL", "remote_thread"); 
    m_dbRemote.setHostName(...); 
    ... 
} 

Как я понимаю, эти новые экземпляры могут также были созданы с помощью QSqlDatabase :: cloneDatabase() и передал эти новые экземпляры конструктору DataHandlerThread (не тестировался).

Итак, похоже, что информация в ссылке «Нитки и модуль SQL» была несколько правильной. По какой-то причине «локальная» связь по-прежнему работала из потока.