1

Let's take a look at the following code:

class CommandRetriever
{
    public:
        CommandRetriever();
        ~CommandRetriever();
    
        void addCommand( QString, Command* );
        void executeCommands();

    private:
        QMap<QString, Command*> m_commands;
};

addCommand should be self-explanatory; it will add a new entry into m_commands. However, let's take a look at the implementation of executeCommands...

void CommandRetriever::executeCommands()
{
    for( auto iter : m_commands.keys() )
    {
        Command *cmd = m_commands.value( iter ); 
         
        // Command, password //
        RemoteConnection *rcon = new RemoteConnection( cmd, "" );

        QThread *thread = new QThread();
        rcon->moveToThread( thread );
        QObject::connect( thread, SIGNAL( started() ), rcon, SLOT( doAsync() ) );
        QObject::connect( rcon, SIGNAL( finished() ), thread, SLOT( quit() ) );
        QObject::connect( rcon, SIGNAL( finished() ), rcon, SLOT( deleteLater() ) );
        QObject::connect( thread, SIGNAL( finished() ), thread, SLOT( deleteLater() ) );
        thread->start();
    }
}

My rcon object is a QObject which has the public slot doAsync() to do work off the main thread. All of this is per Qt official examples and what I was able to muster from various blogs.

This is a completely console-based program, so I have no Windows, Widgets, or event loops to work with.


The Problem

What happens is that my program will exit before any asynchronous work is able to be done (e.g. connect to a remote host, write data, etc). Sometimes, if I'm lucky, my threads will do work fast enough to output something, so I know that the threads are working as they should. My question is: How do I keep my main program running until my threads finish the work? Is there an official way of doing this in QThread? Because I haven't seen anything in the docs.

Thanks!


Addendum April 20, 2015

Although the accepted answer made by Jeremy in this question is correct, it makes less sense for console-based applications, where an event loop is typically not needed.

Thus, I asked a new question, and found an answer for those in search of using threads without Qt event loop non-sense:

QThread never quits due to QCoreApplication event loop

Community
  • 1
  • 1
Kenny Worden
  • 4,335
  • 11
  • 35
  • 62

1 Answers1

3

The method you are looking for is QThread::wait(). Call it on each thread object, from your main thread, before starting your program's cleanup/exit stage. It will wait until the thread has exited before returning.

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
  • Thanks for your speedy reply... but how would this work with multiple threads? Would I put it in the `for` loop? Or would I keep track of all of the threads in a map (or another container) and wait for all of the threads to finish? – Kenny Worden Apr 14 '15 at 02:44
  • The latter -- put the wait() calls into a separate for-loop. Putting the wait() call in the same for loop would mean that thread #2 wouldn't get launched until after thread #1 had exited, which would defeat the purpose of spawning threads. – Jeremy Friesner Apr 14 '15 at 04:12
  • Thanks Jeremy, I'll update my question with the implemented solution and accept the answer when I can. – Kenny Worden Apr 14 '15 at 12:37
  • Jeremy; my `QThread::wait()` functions block the main thread and never return. Can you help me out? – Kenny Worden Apr 15 '15 at 02:08
  • Most likely the thread is never exiting. Does quit() ever get called in the thread? – Jeremy Friesner Apr 15 '15 at 04:38