QTimer::timeout not firing when long calculation, with processEvents in it, running.



  • Dear,
    I have a very basic question, but I don't get there.

    I have a timer timing out every 500ms. The associated function launches a long calculation, provided that calculation is not running yet.

    I was understanding that , provided the long running calculation does a processEvents() every now and then, that timer should stay timing out about all 500ms. But it doesn't. It does only when the calculation ended.

    Can you help me pointing out where I might be wrong and how to solve ?

    The code is as trivial as I describe :

    dlMD5Copy::dlMD5Copy(int& Argc, char* Argv[]) : 
      QCoreApplication(Argc,Argv)
      {
      QObject::connect(&m_Timer,&QTimer::timeout,this,&dlMD5Copy::OnTimer);
      m_Running = false;
      m_Timer.start(500);
      exec();
      }
    
    void dlMD5Copy::OnTimer()
      {
      printf("FOOBAR OnTimer()\n");
      if (not m_Running)
        {
        Calculation();
        }
      }
    
    void dlMD5Copy::Calculation()
      {
      m_Running = true;
      m_X = 0;
      printf("FOOBAR Calculation start\n");
      auto Time = QTime();
      Time.start();
      for (int i=0; i<10000; i++)
        {
        if (Time.elapsed()>100)
          {
          Time.restart();
          printf(".\n");
          processEvents();
          }
        for (int j=0; j<10000; j++)
          {
          m_X += sqrt(i*j)*sqrt(i*j);
          }
        }
      printf("FOOBAR Calculation end %lu\n",m_X);
      m_Running = false;
      }
    
    int main(int Argc, char* Argv[]) 
      {
      dlMD5Copy MD5Copy(Argc,Argv);
      }
    

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Every now and then might suffice but did you benchmark your loops ?

    In any case, for this kind of operation where you want to keep your main thread responsive you should consider QtConcurrent.

    Hope it helps



  • @SGaist

    Thanks for the response.

    I'm not sure what you mean with 'benchmark the loops'. In any case, the processEvents is called every 100ms, where the timeout event is every 500ms. Visual feedback (the printf) proves the intent is correct.

    It just appears that the processEvents() does not result in the timeout event being processed.

    I might have a misconception, but I don't know where ?

    Of course this is a stripdown of a larger problem, where QtConcurrent is less of an option. Thanks for the suggestion though.



  • @jdla

    Dear,

    I'm going to answer my own question.
    Hope future readers will appreciate :)

    Apparently the timer event (timeout) is not generated when previous event is not yet finished.
    The quite simple fix is as follows :
    (i) make Calculation() a slot.
    (ii) invoke it as QMetaObject(this,"Calculation",Qt::QueuedConnection);

    Then the whole setup responds as expected, i.e. the timeouts are processed every 500ms, even if the calculation is still running. processEvents stays needed in order not to block the event loop.


Log in to reply
 

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