QtConcurrent.run() with a c++11 lambda that captures a reference to "this" to emit signal

6.7k views Asked by At

While this works, I have this strange feeling my QObject emit is not threadsafe and the fact that this hasn't exploded yet is just luck.

void LoginController::attemptLogin(QString username, QString password)
{
    emit loginAttemptStatus(QString("Connecting to service..."));
    QFuture<bool> future = QtConcurrent::run([&](QString username, QString password){
            // fake a long running operation
            QThread::sleep(1);
            emit loginAttemptStatus(QString("Connected to service..."));
            // a dumb test login
            QString u("asdf");
            bool success = username.compare( u ) == 0;
            if ( success ) {
                emit loginAttemptStatus(QString("Success..."));
            } else {
                emit loginAttemptStatus(QString("Failure..."));
            }
            return success;
    }, username, password);
    this->watchLoginAttempt.setFuture(future);
}

So, does capturing a reference to this going to cause problems?

Because I think it is but I cannot find a definitive answer.

2

There are 2 answers

0
Marek R On BEST ANSWER

The only case when it can explode, is when you destroy LoginController before lambda expression ends. Proper handling of watchLoginAttempt (future) should prevent this.

0
ratchet freak On

emitting is thread-safe as long as the connections to the slots are not QT::DirectConnection or QT::BlockingQueuedConnection where there may be issues with different threads

connect uses Qt::AutoConnection by default which ensure the correct action is taken no matter which thread does the emitting