ich hab eine SQLite-Datenbank, auf die sowohl aus dem GUI-Thread als auch aus einem Worker-Thread zugegriffen wird (werden soll). Der GUI-Thread liest nur reine Informationen aus, der Worker-Thread allerdings Binaerdaten, was laenger dauert und die GUI blockieren wuerde. Nun habe ich da einige Probleme, v.a. weil ich neu auf dem Gebiet des Multithreading bin. Also, erstmal der Thread:
header:
Code: Alles auswählen
#ifndef BINARYLOADER_H
#define BINARYLOADER_H
#include <QImage>
#include <QObject>
#include <QSize>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
const int TYPE_BINARY = 0;
const int TYPE_IMAGE = 1;
class BinaryLoader : public QThread
{
Q_OBJECT
public:
BinaryLoader ( );
~BinaryLoader ( );
public slots:
void getData ( QString, int, const int type = TYPE_BINARY );
signals:
void binaryLoaded ( int handle, QByteArray );
void imageLoaded ( int handle, QImage );
protected:
void run();
private:
QMutex mutex;
QWaitCondition condition;
bool restart;
bool working;
int idx, type, handle;
QString tableName;
QSize size;
};
#endif // BINARYLOADER_HCode: Alles auswählen
#include <QtSql>
#include "BinaryLoader.h"
BinaryLoader::BinaryLoader ( ) : QThread ( ),
restart ( false ), working ( false ), idx ( -1 )
{
}
BinaryLoader::~BinaryLoader()
{
mutex.lock();
condition.wakeOne();
mutex.unlock();
wait();
}
void BinaryLoader::getData ( QString tableName, int id, const int type )
{
mutex.lock();
this->idx = id;
this->tableName = tableName;
this->type = type;
mutex.unlock();
qDebug() << tableName << "\t" << id;
if ( !isRunning() )
start();
else
{
// already running, wake up whenever ready
restart = true;
condition.wakeOne();
}
}
void BinaryLoader::run()
{
qDebug() << "run()";
// copy necessary data
mutex.lock();
this->working = true;
QString tableName = this->tableName;
int index = this->idx;
int t = this->type;
mutex.unlock();
bool good = true;
QString connectionName = QString ( "threadDB_%1_%2" ).arg ( tableName ).arg ( index );
QSqlDatabase db = QSqlDatabase::addDatabase ( "QSQLITE", connectionName );
db.setDatabaseName ( QSqlDatabase::database().databaseName () );
db.open();
QSqlQuery query ( db );
query.prepare ( QString ( "SELECT data FROM %1 WHERE id = :id" ).arg ( tableName ) );
query.bindValue ( ":id", index+1 );
if ( !query.exec() ) good = false;
if ( !query.next() ) good = false;
if ( good )
{
switch ( t )
{
case TYPE_BINARY:
emit binaryLoaded ( handle, query.value ( 0 ).toByteArray ( ) );
break;
case TYPE_IMAGE:
emit imageLoaded ( handle, QImage::fromData ( query.value ( 0 ).toByteArray ( ) ) );
break;
default:
break;
}
}
db.close();
db = QSqlDatabase();
// we are ready
mutex.lock();
this->working = false;
mutex.unlock();
// put to sleep
mutex.lock();
if ( !this->restart )
condition.wait ( &mutex );
restart = false;
mutex.unlock();
}Code: Alles auswählen
loader->getData ( QString ( "splashes" ), 0, TYPE_IMAGE );
loader->getData ( QString ( "splashes" ), 1, TYPE_IMAGE );
loader->getData ( QString ( "splashes" ), 2, TYPE_IMAGE );
loader->getData ( QString ( "splashes" ), 3, TYPE_IMAGE );Code: Alles auswählen
connect ( loader, SIGNAL ( imageLoaded ( int, QImage ) ), this, SLOT ( display ( int, QImage ) ) );Ich vermute dass ich mich entweder mit dem Mutex vertan habe oder dass die restart-Funktionen nicht funktionieren.qDebug() hat geschrieben:"splashes" 0
run()
"splashes" 1
"splashes" 2
"splashes" 3