Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QThread correct usage

QThread correct usage

Scheduled Pinned Locked Moved Unsolved General and Desktop
qthreadmultithreadc++
5 Posts 2 Posters 2.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • shavS Offline
    shavS Offline
    shav
    wrote on last edited by
    #1

    Hi everyone!

    I have a images gallery application. All images I'm loading in QThread. In QtCreator all works fine (Release and Debug mode). But if I try to load my app just click on MyApplication.app I can't get images list only at first time. When I try to refresh the list I'm receiving error:

    2018-07-20 12:48:36.834 ShavSample[15543:506104] Persistent UI failed to open file file:///Users/andrewsh/Library/Saved%20Application%20State/com.consultica.ShavSample.savedState/window_1.data: Too many open files (24)
    QThreadPipe: Unable to create pipe: Too many open files
    QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe
    Abort trap: 6
    

    I'm using Qt 5.11 on macOS 10.13.6.
    Create a worker:

    ShavGetImagesInfoWorker* worker = new ShavGetImagesInfoWorker(urls, callback);
    if(!ShavTaskManager::isObjectCreated()) {
        ShavTaskManager::initManager();
    }
    ShavTaskManager::shared()->startWork(worker);
    

    Start thread:

    if(worker) {
        m_tasks.append(worker);
        QThread* newThread = new QThread();
        connect(newThread, &QThread::started, worker, &ShavThreadWorker::run);
        connect(worker, &ShavThreadWorker::finished, this, &ShavTaskManager::onFinished);
        connect(worker, &ShavThreadWorker::finished, newThread, &QThread::quit);
        connect(newThread, &QThread::finished, newThread, &QObject::deleteLater);
        worker->moveToThread(newThread);
        newThread->start(static_cast<QThread::Priority>(priority));
    }
    

    All worker is a subclass from class:

    class ShavThreadWorker : public QObject
    {
            Q_OBJECT
        private:
            ShavTaskResult* m_result;
            ShavTaskResult* m_progress;
            QMutex m_mutex;
        protected:
            virtual QObject* doTaskAction();
            void updateProgress(QVariant value, QVariant total, QVariant userData = QVariant());
        public:
            explicit ShavThreadWorker(QJSValue callback, QObject *parent = nullptr);
            explicit ShavThreadWorker(QJSValue callback, QJSValue progress, QObject *parent = nullptr);
            ~ShavThreadWorker();
        signals:
            void finished();
        private slots:
            inline void onFinishedResult() {
                emit finished();
            }
        public slots:
            void run();
            inline void stop() {
                this->thread()->requestInterruption();
            }
     };
    

    and implementation of calls:

    QObject *ShavThreadWorker::doTaskAction() {
        return nullptr;
    }
    
    void ShavThreadWorker::updateProgress(QVariant value, QVariant total, QVariant userData) {
        if(userData.isNull()) {
            QMetaObject::invokeMethod(m_progress, "updateProgress", Qt::QueuedConnection,
                                      Q_ARG(QVariant, value), Q_ARG(QVariant, total));  //Main thread
        } else {
            QMetaObject::invokeMethod(m_progress, "updateProgress", Qt::QueuedConnection,
                                      Q_ARG(QVariant, value), Q_ARG(QVariant, total), Q_ARG(QVariant, userData));  //Main thread
        }
    }
    
    
    ShavThreadWorker::ShavThreadWorker(QJSValue callback, QObject *parent) : QObject(parent) {
        static int index = 0;
        setObjectName(QString("%1_%2").arg(metaObject()->className()).arg(index));
        index += 1;
    
        m_result = new ShavTaskResult(callback);
        connect(m_result, SIGNAL(finished()), SLOT(onFinishedResult()));
        m_progress = nullptr;
    }
    
    ShavThreadWorker::ShavThreadWorker(QJSValue callback, QJSValue progress, QObject *parent) : QObject(parent) {
        static int index = 0;
        setObjectName(QString("%1_%2").arg(metaObject()->className()).arg(index));
        index += 1;
    
        m_result = new ShavTaskResult(callback);
        connect(m_result, SIGNAL(finished()), SLOT(onFinishedResult()));
        m_progress = new ShavTaskResult(progress);
    }
    
    ShavThreadWorker::~ShavThreadWorker() {
    #ifdef QT_DEBUG
        qDebug()<<metaObject()->className()<<"was released!";
    #endif
    }
    
    void ShavThreadWorker::run() {
        m_mutex.lock();
        QObject* res = doTaskAction();
        if(m_result != nullptr) {
            res->moveToThread(qApp->thread());
            QMetaObject::invokeMethod(m_result, "sendResult", Qt::QueuedConnection, Q_ARG(QObject*, res));  //Main thread
        } else {
            onFinishedResult();
        }
        m_mutex.unlock();
    }
    

    Mac OS and iOS Developer

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      Having too many threads makes performance worse than having just 1.

      Rather than having a new thread having time you should distribute the work among QThread::IdealThreadCount threads

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      3
      • shavS Offline
        shavS Offline
        shav
        wrote on last edited by shav
        #3

        Thanks for the reply! Could you share links to the example how to use QThread::IdealThreadCount? In Qt docs I can't find examples for this.

        P.S. Also I try to use QThreadPool for call task But this also not working :(

        Mac OS and iOS Developer

        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          The closest i have to an example is https://github.com/VSRonin/ChatExample/blob/master/QtSimpleChatServerThreaded/chatserver.cpp

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          4
          • shavS Offline
            shavS Offline
            shav
            wrote on last edited by
            #5

            Thanks, I will check!

            Mac OS and iOS Developer

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved