PDA

View Full Version : Running Thread multiple Times



totosugito
6th February 2015, 04:40
Hi,
I am create a simple window like attached image.
10942

The algorithm is like this. When user move the scrollbar, the program will create a thread using scrollbar index as the ID.
I am try to create worker class as an object like below :

worker.h

#ifndef WORKER_H
#define WORKER_H

#include <QObject>
#include <QMutex>

class workerThread;
class Worker : public QObject
{
Q_OBJECT

public:
explicit Worker(QObject *parent = 0);
void requestWork(int id);
void abort();
void run();
void runThread(int id);
private:
bool _abort;
bool _working;
QMutex mutex;
int ID;
bool prepareThread(workerThread *&thread);
workerThread *thisThread;
signals:
void workRequested();
void valueChanged(const QString &value);
void finished();

public slots:
void doWork();
void thisThreadStarted();
void thisThreadFinished();
};

#include <QThread>
class workerThread : public QThread
{
Q_OBJECT
public:
workerThread(Worker *workerThr):workerThr(workerThr){}
virtual ~workerThread(){}

void run() {workerThr->run();}

protected:
Worker *workerThr;
};

#endif // WORKER_H

worker.cpp

#include "worker.h"
#include <QTimer>
#include <QEventLoop>

#include <QThread>
#include <QDebug>

Worker::Worker(QObject *parent) :
QObject(parent)
{
_working =false;
_abort = false;
thisThread = NULL;
}

void Worker::abort()
{
mutex.lock();
if (_working)
{
_abort = true;
//qDebug()<<"Abort "<<QString::number(ID);
}
mutex.unlock();
}

void Worker::run()
{
doWork();
}

void Worker::runThread(int id)
{
//abort thread
abort();

//check if thread still run
//check thread every 10ms
while(thisThread)
{
QEventLoop loop;
QTimer::singleShot(10, &loop, SLOT(quit()));
loop.exec();
}

mutex.lock();
_working = true;
_abort = false;
ID = id;
mutex.unlock();

//run the new thread
thisThread = NULL;
prepareThread(thisThread);
thisThread->start();
}


void Worker::doWork()
{
qDebug()<<"Process "<<QString::number(ID);
for (int i = 0; i < 10; i ++)
{
// Checks if the process should be aborted
mutex.lock();
bool abort = _abort;
mutex.unlock();

if (abort)
{
qDebug()<<"Aborting "<<QString::number(ID);
break;
}
else
{
// add very heavy process
QEventLoop loop;
QTimer::singleShot(200, &loop, SLOT(quit()));
loop.exec();
}
}

// Set _working to false, meaning the process can't be aborted anymore.
mutex.lock();
_working = false;
mutex.unlock();

qDebug()<<"Finished "<<QString::number(ID);
emit finished();
}

bool Worker::prepareThread(workerThread *&thread)
{
thread = new workerThread(this);
connect(thread, SIGNAL(started()), this,
SLOT(thisThreadStarted()), Qt::BlockingQueuedConnection);
connect(thread, SIGNAL(finished()), this,
SLOT(thisThreadFinished()), Qt::BlockingQueuedConnection);
connect(thread, SIGNAL(terminated()), this,
SLOT(thisThreadFinished()), Qt::BlockingQueuedConnection);

return true;
}

void Worker::thisThreadStarted()
{

}

void Worker::thisThreadFinished()
{
thisThread = NULL;
}

But, I get the problem. When I move the scroolbar to another index (from 1 to 314). I hope the program process the last 314th index when I dont move scrollbar again. But, I get the debug message the program still process the previous index.
Aborting "8"
Finished "8"
Process "314"
Finished "314" <--- I hope the program stop in here and not process the previous ID
Process "311"
Finished "311"
Process "309"
Finished "309"
Process "307"
Finished "307"
Process "304"
Finished "304"

Please help me how to solve this problem.
I have attached my full code.
Thank you for your attention.

best regards,

totosugito

anda_skoa
6th February 2015, 09:56
That looks like a very complicated setup.

Might be easier to just implement that in the thread class directly.

You need a method to set the ID to process and the loop in run() regularily checks its current ID against the one set from outside.
If there is a difference you abort the current ID, get the new external ID as the new current ID and start over.

Cheers,
_