[SOLVED] run a function in another thread



  • Hi,
    Let's say i have a MainWindow and a button on it and on it's button click i want to run a few functions each one in a separate thread. how can i achieve this?

    @void MainWindow::on_pushButton_clicked()
    {
    function1(); // Thread 1
    function2(); // Thread 2
    function3(); // Thread 3
    }@
    these functions are not related to each other so they don't need to be synced together.

    i already tried below code as an example however no luck :-(
    @
    void MainWindow::on_pushButton_clicked()
    {
    QThread thread;
    QThread::currentThread()->setObjectName("MainThread");
    thread.setObjectName("CustomThread");
    MyClass obj;
    obj.moveToThread(&thread);
    thread.start();
    if(thread.isRunning())
    {
    obj.sayHello();
    thread.quit();
    }
    }

    void MyClass::sayHello()
    {
    QString s1 = QThread::currentThread()->objectName();
    }
    @
    i get "MainThread" in s1.



  • Hi,

    Try this,

    Very easy, and wil run each function in a pool thread,

    Look for QtConcurrent in dicumentation.

    @
    #include <QtConcurrent>

    void MainWindow::on_pushButton_clicked()
    {
    QFuture<void> future = QtConcurrent::run( function1() );  // Thread 1
    QFuture<void> future = QtConcurrent::run( function2() );  // Thread 2
    QFuture<void> future = QtConcurrent::run( function3() );  // Thread 3
    }
    @



  • Thanks.
    i tried that and i get: "error: invalid use of void expression"



  • [quote author="stevenceuppens" date="1380785595"]Hi,

    Try this,

    Very easy, and wil run each function in a pool thread,

    Look for QtConcurrent in dicumentation.

    @
    #include <QtConcurrent>

    void MainWindow::on_pushButton_clicked()
    {
    QFuture<void> future = QtConcurrent::run( function1() );  // Thread 1
    QFuture<void> future = QtConcurrent::run( function2() );  // Thread 2
    QFuture<void> future = QtConcurrent::run( function3() );  // Thread 3
    }
    @[/quote]

    Thanks.
    i tried that and i get: “error: invalid use of void expression”
    and by the way, QFuture is asynchronous so it's not as fast as threads! i need high performance.



  • I think, you have first to read how QThread works, how Qt suggests to use QThreads
    very good example given "here":http://qt-project.org/doc/qt-5.0/qtcore/qthread.html



  • QThread class itself is not the thread, more the controller..

    indeed, dive into the Docs, to get into QThread..

    Take care with "QFuture is asynchronous so it’s not as fast as threads"..
    depends on what you do.. QFuture "represents the result of an asynchronous computation"

    Below working example of QtConcurrent..
    @

    #include <QCoreApplication>
    #include <QtConcurrent/QtConcurrent>

    // global function
    void myFuncion1()
    {
    qDebug() << "Function1: " << QThread::currentThread();
    }

    class MyClass
    {
    public:
    // static function
    static void myFunction2() { qDebug() << "Function2: " << QThread::currentThread(); }

    // member function
    void myFunction3() { qDebug() << "Function3: " << QThread::currentThread(); }
    

    };

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    qDebug() << "MainThread: " << QThread::currentThread();
    
    QFuture<void> future1 = QtConcurrent::run( myFuncion1 );  // Thread 1
    
    QFuture<void> future2 = QtConcurrent::run( MyClass::myFunction2 );  // Thread 2
    
    MyClass myClass;
    QFuture<void> future3 = QtConcurrent::run( myClass, &MyClass::myFunction3 );  // Thread 3
    
    return a.exec&#40;&#41;;
    

    }
    @



  • [quote author="vladstelmahovsky" date="1380789761"]I think, you have first to read how QThread works, how Qt suggests to use QThreads
    very good example given "here":http://qt-project.org/doc/qt-5.0/qtcore/qthread.html[/quote]

    thanks for the link, it was helpful.
    but there is something in that example which differs from my case!
    @Controller() {
    Worker *worker = new Worker;
    worker->moveToThread(&workerThread);
    connect(workerThread, &QThread::finished, worker, &QObject::deleteLater);
    connect(this, &Controller::operate, worker, &Worker::doWork); // here
    connect(worker, &Worker::resultReady, this, &Controller::handleResults);
    workerThread.start();
    }@

    connect(this, &Controller::operate, worker, &Worker::doWork); //
    i dont have signals like "operate" in here, i just want to run a function
    not a slot! so i'm not using signals and slot approach. i just simply want to run a function(not a slot because i dont have a signal for it) in a separate thread.



  • If you want to do it with "QThread":http://qt-project.org/doc/qt-4.7/qthread.html rather than QtConcurrent then the following is a full, simple example:

    myobject.h
    @
    #ifndef MYOBJECT_H
    #define MYOBJECT_H

    #include <QObject>

    class MyObject : public QObject
    {
    Q_OBJECT
    public:
    explicit MyObject(QObject *parent = 0);

    public slots:
    void sayHello();
    };

    #endif // MYOBJECT_H
    @

    myobject.cpp
    @
    #include "myobject.h"
    #include <QDebug>
    #include <QThread>

    MyObject::MyObject(QObject *parent) : QObject(parent) {}

    void MyObject::sayHello(){
    qDebug() << "Hello from: " << QThread::currentThread()->objectName();
    }
    @

    main.cpp
    @
    #include <QtCore/QCoreApplication>
    #include <QThread>
    #include <QObject>
    #include "myobject.h"

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    QThread::currentThread()->setObjectName("Main Thread");
    
    MyObject myObject;
    
    QThread thread;
    thread.setObjectName("My Thread");
    QObject::connect(&thread, SIGNAL(started()), &myObject, SLOT(sayHello()));
    QObject::connect(&thread, SIGNAL(finished()), &a, SLOT(quit()));
    
    myObject.moveToThread(&thread);
    thread.start();
    
    return a.exec&#40;&#41;;
    

    }
    @

    You can't call a method of an object in another thread directly so instead you use signals and slots, which are thread safe, to it for you and to inform you of when the thread has started and finished.

    Hope this helps ;o)



  • thanks guys your information was very helpful and now i have a better understanding of QThread and QFuture :-).

    • You can’t call a method of an object in another thread directly so instead you use signals and slots.*

    this was my ambiguity in QThread. thanks a million.



  • @jazzycamel

    You can cal a method directly trough the new Qt5 connect syntax,
    example below works, but do you know its thread-safe?

    (i think is is.. but not 100% sure... )

    anyway if you want to be able to use the function

    "moveToThread()" on your workerObject

    your worker has to be QObject derived... so making a SLOT in myObject is not that expensive anymore...

    main.cpp
    @

    #include <QCoreApplication>
    #include <QThread>

    #include "myobject.h"

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    QThread::currentThread()->setObjectName("Main Thread");
    
    MyObject myObject;
    
    QThread thread;
    thread.setObjectName("My Thread");
    
    QObject::connect(&thread, &QThread::started, &myObject, &MyObject::doSomething);
    QObject::connect(&thread, SIGNAL(finished()), &a, SLOT(quit()));
    
    myObject.moveToThread(&thread);
    thread.start();
    
    return a.exec&#40;&#41;;
    

    }
    @

    myobject.h
    @

    #ifndef MYOBJECT_H
    #define MYOBJECT_H

    #include <QObject>

    class MyObject : public QObject
    {
    Q_OBJECT

    public:
    explicit MyObject(QObject *parent = 0);

    void doSomething();
    

    };

    #endif // MYOBJECT_H
    @

    myobject.cpp
    @
    #include "myobject.h"
    #include <QDebug>
    #include <QThread>

    MyObject::MyObject(QObject *parent) :
    QObject(parent)
    {
    }

    void MyObject::doSomething()
    {
    qDebug() << "Hello from: " << QThread::currentThread()->objectName();
    }
    @



  • i see!
    so it's only the matter of being thread safe or not!
    hmmm... you're right, it's really a hard job to make sure your function is thread safe.
    Thank you all.



  • Using signals and slots to communicate between threads is thread-safe by intent and design as the long as the connection type is appropriate (something Qt will establish for itself if you use the default value of Qt.AutoConnection).

    QObject's themselves are not guaranteed to be thread safe, it is up to the developer to ensure their own implementation using QObject is thread-safe. As long as care is taken when accessing any shared objects (mutex's, semaphores etc) it shouldn't be too onerous.

    I have used the method outlined in my exmaple for creating numerous threads in numerous projects without issue and it is certainly a safer and more reliable method than subclassing QThread itself (IMHO).


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.