QNetworkAccessManager падает при удалении - PullRequest
4 голосов
/ 13 июня 2011

У меня есть класс 'Downloader', полученный из QObject, который запускается в рабочем потоке.Когда поток запущен, загрузчик создает объект QNetworkAccessManager в куче и начинает запрашивать файлы.Я отслеживаю, сколько файлов было запрошено и получено.Получив все файлы, я удаляю объект QNetworkAccessManager и выхожу из потока.Моя проблема заключается в том, что удаление объекта диспетчера вызывает сбой независимо от того, когда и где я это делаю.Я даже попробовал manager-> deleteLater ().Если я не удаляю его, мой код работает отлично, но я знаю, что там утечка памяти.Вот урезанная версия моего кода.

Создание загрузчика и потока и настройка сигналов таким образом, чтобы запуск потока начинал загрузки, а после завершения загрузки поток останавливается:

QThread thread;
Downloader downloader;
downloader.setFiles(files);
downloader.moveToThread(&thread);

downloader.connect(&thread, SIGNAL(started()), SLOT(downloadFiles()));
thread.connect(&downloader, SIGNAL(downloadsFinished()), SLOT(quit()));

thread.start();

Реализация для загрузчика:

void Downloader::downloadFiles()
{
    QNetworkAccessManager *manager = new QNetworkAccessManager();
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)));

    receivedCount = 0;
    requestCount = files.count();

    for (QStringList::const_iterator pos = files.begin(); pos != files.end(); ++pos)
    {
        QUrl url(*pos);
        manager->get(QNetworkRequest(url));
    }
}


void Downloader::finished(QNetworkReply *reply)
{
    // *** Get the file data and process it *** //

    ++receivedCount;
    reply->deleteLater();

    if (receivedCount == requestCount)
    {
//        manager->deleteLater();
        emit downloadsFinished();
    }
}

Закомментированная строка приведет к падению приложения.Даже удаление менеджера в деструкторе Downloader или установка загрузчика в качестве родителя менеджера приведет к сбою приложения.

Сначала я попытался создать менеджер как обычную переменную-член в стеке, но это вызывает собственные ошибкипоскольку менеджер будет создан в потоке GUI, а затем попытается создать дочерние элементы в другом потоке.

И прежде чем кто-либо скажет: "QNetworkAccessManager является асинхронным. Зачем использовать его в рабочем потоке?"У меня есть причины.Это не должно быть НИЧЕГО, чтобы сделать что-то подобное.

1 Ответ

4 голосов
/ 13 июня 2011

Единственная очевидная проблема - ниже, но я не уверен, что вы опубликовали весь свой код или нет

void Downloader::downloadFiles()
{
    QNetworkAccessManager *manager = new QNetworkAccessManager();

Вы создаете local QNetworkAccessManager *manager в своем методе, ноне сохраняя ссылку на него, а затем пытаясь получить к нему доступ в методе finish ().

Вы должны назначить new QNetworkAccessManager(); переменную-член!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...