title: QThread: Making parallel execution with GUI-Feedback blocking?
body: <h1>Scenario</h1>
  
  <p>Lets say, I have a procedure called <code>parallelRun</code>. It would take a list of workers, each having a <code>getWorkAmount():int</code>, a <code>run()</code> method, a <code>finished()</code> signal and a <code>cancel()</code> slot:</p>
  
  <pre><code>void parallelRun( std::vector&lt; Worker* &gt; workers );
  </code></pre>
  
  <p>Its implementation should:</p>
  
  <h2>1. Open a <code>QPogressDialog</code>:</h2>
  
  <pre><code>unsigned int totalWorkAmount = 0;
  for( auto it = workers.begin(); it != workers.end(); ++it )
  {
      totalWorkAmount += ( **it ).getWorkAmount();
  }
  
  LoadUI ui( 0, totalWorkAmount, this );
  </code></pre>
  
  <p>with</p>
  
  <pre><code>class LoadUI : public QObject
  {
      Q_OBJECT
  
  public:
  
      LoadUI( int min, int max, QWidget* modalParent )
          : totalProgres( 0 )
          , progressDlg( "Working", "Abort", min, max, modalParent )
      {
          connect( &amp;progressDlg, SIGNAL( canceled() ), this, SLOT( cancel() ) );
  
          progressDlg.setWindowModality( Qt::WindowModal );
          progressDlg.show();
      }
  
      bool wasCanceled() const
      {
          return progressDlg.wasCanceled();
      }
  
  public slots:
  
      void progress( int amount )
      {
          totalProgres += amount;
  
          progressDlg.setValue( totalProgres );
          progressDlg.update();
  
          QApplication::processEvents();
      }
  
  signals:
  
      void canceled();
  
  private slots:
  
      void cancel()
      {
          emit canceled();
      }
  
  private:
  
      int totalProgres;
      QProgressDialog progressDlg;
  }
  </code></pre>
  
  <h2>2. Create one thread for each worker</h2>
  
  <pre><code>std::vector&lt; std::unique_ptr&lt; QThread &gt; &gt; threads;
  for( auto it = workers.begin(); it != workers.end(); ++it )
  {
      std::unique_ptr&lt; QThread &gt; thread( new QThread() );
  
      Worker* const worker = *it;
      worker-&gt;moveToThread( thread.get() );
  
      QObject::connect( worker, SIGNAL( finished() ), thread.get(), SLOT( quit() ) );
      QObject::connect( &amp;ui, SIGNAL( canceled() ), worker, SLOT( cancel() ) );
      QObject::connect( *it, SIGNAL( progressed( int ) ), &amp;ui, SLOT( progress( int ) ) );
  
      thread-&gt;start( priority );
  
      threads.push_back( std::move( thread ) );
  }
  </code></pre>
  
  <h2>3. Run them simultaneously</h2>
  
  <pre><code>for( auto it = workers.begin(); it != workers.end(); ++it )
  {
      QMetaObject::invokeMethod( *it, "run", Qt::QueuedConnection );
  }
  </code></pre>
  
  <p><code>load()</code> is run when the user clicks an UI-button.</p>
  
  <h1>Problem</h1>
  
  <p>How am I supposed to extend this code, if I want to make <code>parallelRun</code> block until all workers are finished, without freezing the <code>QProgressDialog</code>?</p>
  
  <h2>Deliberations</h2>
  
  <h3>Using a barrier</h3>
  
  <p>I tried adding the following code at the end of the <code>parallelRun</code> routine:</p>
  
  <pre><code>QApplication::processEvents();
  for( auto it = threads.begin(); it != threads.end(); ++it )
  {
      ( **it ).wait();
  }
  </code></pre>
  
  <p>The impact of this few lines of extra-code is, that <code>LoadUI::progress</code> is <em>never entered</em>, since the GUI-thread is <em>asleep</em> and therefore it's event loop isn't processed: In Qt, signals are delivered to slots by posting them to the event loop of the thread, associated to the object the slot belongs to. This is why the <code>progressed</code> signal of a worker is never delivered.</p>
  
  <p>I think, the appropriate solution would be to run <code>QApplication::processEvents()</code> <em>within the GUI-thread</em> anytime a <code>progressed</code> signal is emitted by a worker. On the other hand, I guess this cannot be done, since the GUI-thread is asleep.</p>
  
  <h3>Another possible solution</h3>
  
  <p>Another possibility would be to use an <em>active waiting</em>-like solution:</p>
  
  <pre><code>for( auto it = threads.begin(); it != threads.end(); ++it )
  {
      while( ( **it ).isRunning() )
      {
          QApplication::processEvents();
      }
  }
  for( auto it = threads.begin(); it != threads.end(); ++it )
  {
      ( **it ).wait();
  }
  </code></pre>
  
  <p>This also requires adding the following line of code right after <code>thread-&gt;start( priority );</code>:</p>
  
  <pre><code>while( !thread-&gt;isRunning() );
  </code></pre>
  
  <p>I don't think that this is a nice solution, but at least it works. How can this be done without the drawbacks of active waiting?</p>
  
  <p>Thanks in advance!</p>