Search code examples
multithreadingqtqthreadqt4.8

use QThread exclusively for an object


EDIT2

Here is the solution that works for the following problem of giving a QThread exclusively to the object.

I've changed the approach for the problem. I don't want to close QThread in MyClass anymore, cause the following solution seems easier and not too bad looking.

My solution is modification of the solution given here: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

The problem with that solution was that QObject worker wasn't really deleted (checked it).

QThread *myThread = new QThread();
SCIntermediary* myObj = new MyClass();
myObj->moveToThread(myThread);
connect(myThread, SIGNAL(started()), myObj, SLOT(setup()));
connect(myObj, SIGNAL(destroyed()), myThread, SLOT(quit()), Qt::DirectConnection);
connect(myObj, SIGNAL(finished()), myObj, SLOT(deleteLater()));
connect(myThread, SIGNAL(finished()), myThread, SLOT(deleteLater()));
myThread -> start();

// do your work bla bla bla

myObj -> finishIt(); // this function only emits finish() signal of myObj
myThread -> wait();

This is the first solution that worked for me destroying both myObj and myThread without any errors or other troubles at all.

ENDOF EDIT

I'm trying to create a class will do some stuff between my client and my server. I'd like it to have it's own thread. So what I did is:

class Myclass : public QObject {
    Q_OBJECT
public:
    Myclass();
    ~Myclass();

private:
    QThread *my_thread;
    QTcpSocket *sock;
}

Here is how I coded my constructor:

Myclass::Myclass(){
    my_thread = new QThread();
    my_thread -> start();
    moveToThread(my_thread);

    sock = new QTcpSocket(this);
    sock -> connectToHost("host", port);
}

This didn't work. It didn't work, because the code for TcpSocket wasn't executed in the same thread the parent object currently is. So what I decided to do is to create slot and signal for setup and emit it in my constructor. Here is how my code looks right now.

class Myclass : public QObject {
    Q_OBJECT
public:
    Myclass();
    ~Myclass();

public slots:
    void setup();

signals:
    void do_setup();

private:
    QThread *my_thread;
    QTcpSocket *sock;
}

And some of it's implementation

Myclass::Myclass(){
    my_thread = new QThread();
    my_thread -> start();
    moveToThread(my_thread);

    connect(this, SIGNAL(do_setup()), this, SLOT(setup()));
    emit do_setup();
}

void Myclass::setup(){
    sock = new QTcpSocket();
    sock -> connectToHost("host", port);
}

Now it works and here comes the sad part - it looks terrible! It's awful and I have no idea how to make it look better or how such pattern should be done in the first place. What would you advice me to do to get the same effect?

Additionally - I have no idea how to write good destructor for this - how to delete QThread smoothly and all the class objects..

EDIT

For now I believe the solution is quite alright - the only problem left is how to write a destructor for that. I have no idea how it can be done here.


Solution

  • For destructor, check out Maya Posch example: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ Since your thread is not child of MyClass, perhaps you can call finish() on thread as last thing in destructor and connect destroyed() signal of MyClass to deleteLater for thread?