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. QBasicTimer::start: Timers cannot be started from another thread issue
Forum Updated to NodeBB v4.3 + New Features

QBasicTimer::start: Timers cannot be started from another thread issue

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 2 Posters 5.8k 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.
  • C Offline
    C Offline
    Cobra91151
    wrote on 30 Aug 2017, 09:48 last edited by Cobra91151
    #1

    Hi! The code works but I get the issue - QBasicTimer::start: Timers cannot be started from another thread. It occurs when I use QEventLoop in the thread.

    Code:

    void Test::checkDBUpdate()
    {
        QEventLoop *checkDBEventLoop;
        QFile *dbFile = new QFile(QString(DB_DIR) + QString(DB_FILE));
        dbFile->open(QIODevice::ReadOnly);
        QTextStream dbTextStream(dbFile);
        QString localDBFile = dbTextStream.readAll();
        QString ftpDBFile = "";
        checkDBEventLoop = new QEventLoop(this);
        QNetworkReply *checkDBReply = netManager->get(QNetworkRequest(dbFtpUrl()));
        connect(checkDBReply, &QNetworkReply::finished, checkDBEventLoop, &QEventLoop::quit);
        checkDBEventLoop->exec();
    
        if (checkDBReply->bytesAvailable()) {
            ftpDBFile = checkDBReply->readAll();
            qDebug() << localDBFile.length();
            qDebug() << ftpDBFile.length();
    
            if (localDBFile.length() != ftpDBFile.length()) {
                emit dbUpdateAvailable();
            } else {
                emit dbLatest();
            }
        }
    
        dbFile->close();
        delete dbFile;
        delete checkDBReply;
        delete checkDBEventLoop;
    }
    

    I don't have any timers set. How to fix the issue? Thanks.

    J 1 Reply Last reply 30 Aug 2017, 10:45
    0
    • C Cobra91151
      30 Aug 2017, 09:48

      Hi! The code works but I get the issue - QBasicTimer::start: Timers cannot be started from another thread. It occurs when I use QEventLoop in the thread.

      Code:

      void Test::checkDBUpdate()
      {
          QEventLoop *checkDBEventLoop;
          QFile *dbFile = new QFile(QString(DB_DIR) + QString(DB_FILE));
          dbFile->open(QIODevice::ReadOnly);
          QTextStream dbTextStream(dbFile);
          QString localDBFile = dbTextStream.readAll();
          QString ftpDBFile = "";
          checkDBEventLoop = new QEventLoop(this);
          QNetworkReply *checkDBReply = netManager->get(QNetworkRequest(dbFtpUrl()));
          connect(checkDBReply, &QNetworkReply::finished, checkDBEventLoop, &QEventLoop::quit);
          checkDBEventLoop->exec();
      
          if (checkDBReply->bytesAvailable()) {
              ftpDBFile = checkDBReply->readAll();
              qDebug() << localDBFile.length();
              qDebug() << ftpDBFile.length();
      
              if (localDBFile.length() != ftpDBFile.length()) {
                  emit dbUpdateAvailable();
              } else {
                  emit dbLatest();
              }
          }
      
          dbFile->close();
          delete dbFile;
          delete checkDBReply;
          delete checkDBEventLoop;
      }
      

      I don't have any timers set. How to fix the issue? Thanks.

      J Offline
      J Offline
      jsulm
      Lifetime Qt Champion
      wrote on 30 Aug 2017, 10:45 last edited by
      #2

      @Cobra91151 Why do you need an event loop? Why not just use Qt in the way it was designed: asynchronously?

      Do you start any threads?

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      C 1 Reply Last reply 30 Aug 2017, 10:52
      0
      • J jsulm
        30 Aug 2017, 10:45

        @Cobra91151 Why do you need an event loop? Why not just use Qt in the way it was designed: asynchronously?

        Do you start any threads?

        C Offline
        C Offline
        Cobra91151
        wrote on 30 Aug 2017, 10:52 last edited by
        #3

        @jsulm

        Yes. The work starts in the thread with connected signals and slots. I use QEventLoop to maintain all check work in the checkDBUpdate() slot.

        J 1 Reply Last reply 30 Aug 2017, 10:54
        0
        • C Cobra91151
          30 Aug 2017, 10:52

          @jsulm

          Yes. The work starts in the thread with connected signals and slots. I use QEventLoop to maintain all check work in the checkDBUpdate() slot.

          J Offline
          J Offline
          jsulm
          Lifetime Qt Champion
          wrote on 30 Aug 2017, 10:54 last edited by
          #4

          @Cobra91151 Can you show where and how you start the thread?

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          C 1 Reply Last reply 30 Aug 2017, 11:01
          0
          • J jsulm
            30 Aug 2017, 10:54

            @Cobra91151 Can you show where and how you start the thread?

            C Offline
            C Offline
            Cobra91151
            wrote on 30 Aug 2017, 11:01 last edited by
            #5

            @jsulm

            Ok.

            Code:

            void AppSettings::checkDatabaseUpdate()
            {
                QThread *dbUpdateThread = new QThread();
                Test *dbUpdate = new Test();
                dbUpdate->moveToThread(dbUpdateThread);
                connect(dbUpdateThread, &QThread::started, dbUpdate, &Test::checkDBUpdate);
                connect(dbUpdate, &Test::dbUpdateAvailable, this, &AppSettings::setDBUpdate);
                connect(this, &AppSettings::dbUpdateConfirmed, dbUpdate, &Test::updateDatabase);
                connect(dbUpdate, &Test::updateDBCompleted, this, &AppSettings::setDBUpdated);
                connect(dbUpdate, &Test::dbLatest, this, &AppSettings::setDBLatest);
                connect(this, &AppSettings::dbUpdateCanceled, dbUpdate, &Test::setUpdateCanceled);
                connect(dbUpdate, &Test::updateDBFinished, dbUpdateThread, &QThread::quit);
                connect(dbUpdate, &Test::updateDBFinished, dbUpdate, &Test::deleteLater);
                connect(dbUpdateThread, &QThread::finished, dbUpdateThread, &QThread::deleteLater);
                dbUpdateThread->start();
            }
            
            J 1 Reply Last reply 30 Aug 2017, 11:08
            0
            • C Cobra91151
              30 Aug 2017, 11:01

              @jsulm

              Ok.

              Code:

              void AppSettings::checkDatabaseUpdate()
              {
                  QThread *dbUpdateThread = new QThread();
                  Test *dbUpdate = new Test();
                  dbUpdate->moveToThread(dbUpdateThread);
                  connect(dbUpdateThread, &QThread::started, dbUpdate, &Test::checkDBUpdate);
                  connect(dbUpdate, &Test::dbUpdateAvailable, this, &AppSettings::setDBUpdate);
                  connect(this, &AppSettings::dbUpdateConfirmed, dbUpdate, &Test::updateDatabase);
                  connect(dbUpdate, &Test::updateDBCompleted, this, &AppSettings::setDBUpdated);
                  connect(dbUpdate, &Test::dbLatest, this, &AppSettings::setDBLatest);
                  connect(this, &AppSettings::dbUpdateCanceled, dbUpdate, &Test::setUpdateCanceled);
                  connect(dbUpdate, &Test::updateDBFinished, dbUpdateThread, &QThread::quit);
                  connect(dbUpdate, &Test::updateDBFinished, dbUpdate, &Test::deleteLater);
                  connect(dbUpdateThread, &QThread::finished, dbUpdateThread, &QThread::deleteLater);
                  dbUpdateThread->start();
              }
              
              J Offline
              J Offline
              jsulm
              Lifetime Qt Champion
              wrote on 30 Aug 2017, 11:08 last edited by
              #6

              @Cobra91151 Is netManager initialized in Test constructor? If so try to do it in Test::checkDBUpdate().
              I do not see any reason to start a thread in AppSettings::checkDatabaseUpdate() which executes a blocking method. Just make Test::checkDBUpdate() non blocking. You really over complicate things.

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              C 1 Reply Last reply 30 Aug 2017, 11:22
              0
              • J jsulm
                30 Aug 2017, 11:08

                @Cobra91151 Is netManager initialized in Test constructor? If so try to do it in Test::checkDBUpdate().
                I do not see any reason to start a thread in AppSettings::checkDatabaseUpdate() which executes a blocking method. Just make Test::checkDBUpdate() non blocking. You really over complicate things.

                C Offline
                C Offline
                Cobra91151
                wrote on 30 Aug 2017, 11:22 last edited by
                #7

                @jsulm

                Yes, netManager (QNetworkAccessManager) is initialized in the Test constructor. I have initialized it in the constructor to access not only for the Test::checkDBUpdate(), but also for the other features which require QNetworkAccessManager. So I can't initialized it twice or in Test::checkDBUpdate().

                AppSettings class is a GUI window and I connect it there to get the result of the work. It's very big and complicated application.

                What do you mean by blocking method?

                J 2 Replies Last reply 30 Aug 2017, 11:34
                0
                • C Cobra91151
                  30 Aug 2017, 11:22

                  @jsulm

                  Yes, netManager (QNetworkAccessManager) is initialized in the Test constructor. I have initialized it in the constructor to access not only for the Test::checkDBUpdate(), but also for the other features which require QNetworkAccessManager. So I can't initialized it twice or in Test::checkDBUpdate().

                  AppSettings class is a GUI window and I connect it there to get the result of the work. It's very big and complicated application.

                  What do you mean by blocking method?

                  J Offline
                  J Offline
                  jsulm
                  Lifetime Qt Champion
                  wrote on 30 Aug 2017, 11:34 last edited by
                  #8

                  @Cobra91151 I mean void Test::checkDBUpdate() is blocking (not returning) until it is finished (that's why you use event loop there, right?). So, you start a thread to execute a blocking method to not block main thread instead of simply making void Test::checkDBUpdate() non blocking. You introduce a complex and error prone work-around (thread) for something you could simply change. Also: why do you use new so often (for example there is no need to allocate dbFile on the heap)? Why not just allocate memory on the stack?

                  Back to this timer issue: you create netManager in constructor and then later move Test to another thread, I guess netManager is still in the main thread.

                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  1
                  • C Cobra91151
                    30 Aug 2017, 11:22

                    @jsulm

                    Yes, netManager (QNetworkAccessManager) is initialized in the Test constructor. I have initialized it in the constructor to access not only for the Test::checkDBUpdate(), but also for the other features which require QNetworkAccessManager. So I can't initialized it twice or in Test::checkDBUpdate().

                    AppSettings class is a GUI window and I connect it there to get the result of the work. It's very big and complicated application.

                    What do you mean by blocking method?

                    J Offline
                    J Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on 30 Aug 2017, 11:42 last edited by
                    #9

                    @Cobra91151 Here a non-blocking solution without any threads (untested!):

                    void Test::checkDBUpdate()
                    {
                        QFile dbFile(QString(DB_DIR) + QString(DB_FILE));
                        dbFile.open(QIODevice::ReadOnly);
                        QTextStream dbTextStream(dbFile);
                        QString localDBFile = dbTextStream.readAll();
                        QNetworkReply *checkDBReply = netManager->get(QNetworkRequest(dbFtpUrl()));
                        connect(checkDBReply, &QNetworkReply::finished, [checkDBReply, localDBFile]() {
                            if (checkDBReply->bytesAvailable()) {
                                QString ftpDBFile = checkDBReply->readAll();
                                qDebug() << ftpDBFile.length();
                    
                                if (localDBFile.length() != ftpDBFile.length()) {
                                    emit dbUpdateAvailable();
                                } else {
                                    emit dbLatest();
                                }
                            }
                            checkDBReply->deleteLater();
                        });
                    }
                    
                    void AppSettings::checkDatabaseUpdate()
                    {
                        Test *dbUpdate = new Test();
                        connect(dbUpdate, &Test::dbUpdateAvailable, this, &AppSettings::setDBUpdate);
                        connect(this, &AppSettings::dbUpdateConfirmed, dbUpdate, &Test::updateDatabase);
                        connect(dbUpdate, &Test::updateDBCompleted, this, &AppSettings::setDBUpdated);
                        connect(dbUpdate, &Test::dbLatest, this, &AppSettings::setDBLatest);
                        connect(this, &AppSettings::dbUpdateCanceled, dbUpdate, &Test::setUpdateCanceled);
                        connect(dbUpdate, &Test::updateDBFinished, dbUpdateThread, &QThread::quit);
                        connect(dbUpdate, &Test::updateDBFinished, dbUpdate, &Test::deleteLater);
                        dbUpdate->checkDBUpdate();
                    }
                    

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    4
                    • C Offline
                      C Offline
                      Cobra91151
                      wrote on 30 Aug 2017, 11:51 last edited by Cobra91151
                      #10

                      @jsulm

                      Thanks for the code but I get errors:

                      error: C4573: the usage of 'CheckUpdates::dbUpdateAvailable' requires the compiler to capture 'this' but the current default capture mode does not allow it
                      

                      When changing lambda to connect(checkDBReply, &QNetworkReply::finished, [checkDBReply, this]() { I get error:

                      error: C3493: 'localDBFile' cannot be implicitly captured because no default capture mode has been specified
                      
                      J 1 Reply Last reply 30 Aug 2017, 12:02
                      0
                      • C Cobra91151
                        30 Aug 2017, 11:51

                        @jsulm

                        Thanks for the code but I get errors:

                        error: C4573: the usage of 'CheckUpdates::dbUpdateAvailable' requires the compiler to capture 'this' but the current default capture mode does not allow it
                        

                        When changing lambda to connect(checkDBReply, &QNetworkReply::finished, [checkDBReply, this]() { I get error:

                        error: C3493: 'localDBFile' cannot be implicitly captured because no default capture mode has been specified
                        
                        J Offline
                        J Offline
                        jsulm
                        Lifetime Qt Champion
                        wrote on 30 Aug 2017, 12:02 last edited by
                        #11

                        @Cobra91151 said in QBasicTimer::start: Timers cannot be started from another thread issue:

                        connect(checkDBReply, &QNetworkReply::finished, checkDBReply, this {

                        Why did you remove localDBFile?

                        connect(checkDBReply, &QNetworkReply::finished, [checkDBReply, localDBFile, this]() {
                        

                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                        C 1 Reply Last reply 30 Aug 2017, 12:08
                        3
                        • J jsulm
                          30 Aug 2017, 12:02

                          @Cobra91151 said in QBasicTimer::start: Timers cannot be started from another thread issue:

                          connect(checkDBReply, &QNetworkReply::finished, checkDBReply, this {

                          Why did you remove localDBFile?

                          connect(checkDBReply, &QNetworkReply::finished, [checkDBReply, localDBFile, this]() {
                          
                          C Offline
                          C Offline
                          Cobra91151
                          wrote on 30 Aug 2017, 12:08 last edited by
                          #12

                          @jsulm

                          Yes, you right. I missed it. Now it works. Thank you.

                          1 Reply Last reply
                          0

                          1/12

                          30 Aug 2017, 09:48

                          • Login

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