Qt: sending signal from a std::thread to GUI thread.

I have an application using Qt as the front end. I do not want to use Qt through out the application as I will be needing to put a different GUI on the application as some point in time.

This means that I have a background thread which is a C++ std::thread object. This thread reads data from the network and passes on messages to the GUI thread for display.

The way that I have approached this is two fold.

1. Poll the data store in the background thread at regular intervals and copy the data I need.
2. Get the background thread to signal the GUI when something important needs to be read.

This post deals with the second approach.

So the GUI thread is basically the main application thread and is pretty much what you would expect it to be:
class MainWindow : public QMainWindow, private Ui_MainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void warningMessage(const std::string &message);
...

private slots:
    void handleWarningButton();
    void newWarningMessageReceived();
...
signals:
    void messageReceived();
...
private:
    std::mutex warningMessageLock_;
    std::queue<std::string> warningMessages_;
    std::queue<std::string> warningMessagesToAcknowledge_;

The method warningMessage is called when I need to pass the warning message to the GUI.
void MainWindow::warningMessage(const std::string &message)
{
    {
        std::lock_guard<std::mutex> guard(warningMessageLock_);
        warningMessages_.push(message);
    }
    emit messageReceived();
}
As can be seen it calls messageReceived with emit.
This caused the method to be called at some point from the GUI thread context:
void MainWindow::newWarningMessageReceived()
{
    std::queue<std::string> messages;
    {
        std::lock_guard<std::mutex> guard(warningMessageLock_);
        std::swap( warningMessages_, messages );
    }
    while (!messages.empty())
    {
        auto message = messages.front();
        messages.pop();
        updateWarning(false, message);
    }
}

When I set up the GUI I set the connection between the signal and slot call thus:
    connect(this, SIGNAL(messageReceived()), this,
            SLOT(newWarningMessageReceived()), Qt::AutoConnection);

Comments