середу, 14 квітня 2010 р.

Проблеми з повторними генераціями сигналу finished для QNetworkReply

Вчора зіткнувся з досить неочевидною проблемою при тестуванні QT-аплікації. Після відсилання мережевого запиту обробка відповіді відбувається у функції, прив'язаній до сигналу finished.
Робота з мережевими запитами в QT описана ось тут Creating_an_HTTP_network_request_in_Qt

Ось, власне, прив'язка у моєму випадку:
connect(_networkManager, SIGNAL(finished(QNetworkReply*)), this,
    SLOT(replyFinished(QNetworkReply*)));

Виявилося, що цей сигнал генерується декілька разів: QNetworkReply завершив роботу, перед знищенням об'єкта QNetworkReply або під час його закриття функціями close() чи abort(). При цьому лише у першому випадку з нього можна щось прочитати, у решті - ні, що призводить до помилок при парсінгу даних і зупинки обробки наступних запитів (у моєму випадку відбувається перевірка статусу попереднього запиту перед відправкою наступного).

Правильним рішенням було відключити всі слоти від сигналів QNetworkReply, щоб не отримувати їх після завершення обробки даних. Ось як це реалізовано:
void MyClass::replyFinished(QNetworkReply* reply) {
    // --------------------------------------
    // Тут насправді міститься обробка даних
    // --------------------------------------

    // Close and clean up.
    m_networkManager->disconnect();
    reply->close();
    reply->deleteLater();
}