2017-01-17 3 views
1

У меня странное поведение с Lambda и таймером на Qt 5.7.1. Вероятно, ошибка от меня.QLocalSocket - QTimer и Lambda

Я запускаю соединение с гнездом и устанавливаю таймер, чтобы проверить, было ли оно подключено или нет через определенное время.

Сигнал, подключенный к розетке, остановит время.

Однако при выполнении следующего таймера таймер не останавливается, даже если вызывается подключенный сигнал.

constructor: 

m_connectTimeout.setInterval(5000); 

connect(&m_socket, &QLocalSocket::connected, [&]() 
{ 
    // this is called first and should stop the timer. 
    m_connectTimeout.stop(); 
}); 


connect(&m_connectTimeout, &QTimer::timeout, [&](){ 
     // this is still called 
}); 

Вот минимальный пример с проблемой воспроизводимого на Qt5.7.1 и Windows, 10.

#include <QtCore> 
#include <QtNetwork> 

#define PIPENAME "testbug" 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    QTimer timer; 
    QLocalSocket socketClient, *socketServer; 
    QLocalServer server; 
    timer.setInterval(2000); 


    QObject::connect(&timer, &QTimer::timeout, [&] 
    { 
     qDebug() << "client connection timed out"; 
     timer.stop(); 
    }); 

    QObject::connect(&socketClient, &QLocalSocket::connected, [&] 
    { 
     qDebug() << "client connected"; 
     timer.stop(); 
    }); 

    QObject::connect(&server, &QLocalServer::newConnection, [&] 
    { 
     qDebug() << "server got connection"; 
     socketServer = server.nextPendingConnection(); 
    }); 

    server.setSocketOptions(QLocalServer::WorldAccessOption); 
    server.listen(PIPENAME); 

    qDebug() << "client connecting. . ."; 
    socketClient.connectToServer(PIPENAME, QLocalSocket::ReadWrite); 
    timer.start(); 

    return a.exec(); 
} 

Выход программы:

client connecting. . . 
client connected 
server got connection 
client connection timed out 

Я также заметил, что это не всегда воспроизводим и кажется случайным.

+0

Выполняет ли '' 'm_connectTimeout.stop()' '' фактически? Установите контрольную точку и посмотрите, выполняется ли она –

+1

. Попробуйте предоставить [MCVE] (https://stackoverflow.com/help/mcve). Я не могу думать о какой-либо причине, почему 'm_connectTimeout.stop()' не останавливает таймер (вы действительно уверены, что он называется первым?). Вот [минимальный пример] (https://gist.github.com/micjabbour/292d14219a20ef00f8d4d1e332916b5c), который работает и не воспроизводит проблему. – Mike

+0

@Victor, да, это действительно работает, у меня на самом деле есть отладочный вывод. – Damien

ответ

1

На самом деле кажется, что код работает, это просто, что соединение происходит так быстро, что timer.stop вызывается перед timer.start.

Запуск таймера перед вызовом подключения к серверу, кажется, решить проблему

m_timer.start(); 
m_socketClient.connectToServer(PIPENAME, QLocalSocket::ReadWrite); 

Это будет означать, что connectToServer делает некоторые вызовы на цикл событий в фоновом режиме, позволяя слотам назвать, еще до того, следующая строка выполнена.

+0

да, это проблема, я писал ответ , Сигнал 'connected()' испускается из 'connectToServer()', и таймер запускается после того, как он был остановлен в вашем слоте. – Mike