Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct


    Qt World Summit: Early-Bird Tickets

    Unsolved QThread correct usage

    General and Desktop
    qthread multithread c++
    2
    5
    1610
    Loading More Posts
    • 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.
    • S
      shav last edited by

      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 Reply Quote 0
      • VRonin
        VRonin last edited by

        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 Reply Quote 3
        • S
          shav last edited by shav

          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 Reply Quote 0
          • VRonin
            VRonin last edited by

            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 Reply Quote 4
            • S
              shav last edited by

              Thanks, I will check!

              Mac OS and iOS Developer

              1 Reply Last reply Reply Quote 0
              • First post
                Last post