Имейте приложение, в котором у меня есть QOBJects, все из которых содержат QNetworkAccessManager. Я знаю, что он предложил использовать только для каждого приложения, но поскольку я делаю намного больше, чем 6 звонков одновременно, мне нужно было это сделать так. Итак, вот как я начинаю темы.
FileUploader *fileUploader = new FileUploader(_fileList);
QThread *fileUploaderThread = new QThread();
fileUploader->moveToThread(fileUploaderThread);
// uploader > model
connect(fileUploader, SIGNAL(progressChangedAt(int)), _model, SLOT(reportProgressChanged(int)), Qt::QueuedConnection);
connect(fileUploader, SIGNAL(statusChangedAt(int)), _model, SLOT(reportStatusChanged(int)), Qt::QueuedConnection);
// uploader > its thread
connect(fileUploader, SIGNAL(canceled()), fileUploaderThread, SLOT(quit()), Qt::QueuedConnection);
connect(fileUploader, SIGNAL(finished()), fileUploaderThread, SLOT(quit()), Qt::QueuedConnection);
// uploader > this
connect(fileUploader, SIGNAL(canceled()), this, SLOT(deleteFinishedUploader()), Qt::QueuedConnection);
connect(fileUploader, SIGNAL(finished()), this, SLOT(deleteFinishedUploader()), Qt::QueuedConnection);
connect(fileUploader, SIGNAL(finishedCurrentUpload()), this, SLOT(uploadNextFileOrFinish()), Qt::QueuedConnection);
// thread > this
connect(fileUploaderThread, SIGNAL(finished()), this, SLOT(checkIfAllThreadsAreFinished()), Qt::QueuedConnection);
connect(fileUploaderThread, SIGNAL(finished()), this, SLOT(deleteFinishedThread()), Qt::QueuedConnection);
// this > uploader
connect(this, SIGNAL(cancel()), fileUploader, SLOT(cancel()), Qt::QueuedConnection);
fileUploaderThread->start();
QMetaObject::invokeMethod(fileUploader, "init", Qt::QueuedConnection);
QMetaObject::invokeMethod(fileUploader, "uploadAt", Qt::QueuedConnection, Q_ARG(int, startIndex));
QMutexLocker locker(&_mutex);
_threadCount++;
Каждый поток начинается с индекса в список, чтобы они могли извлекать то, что им нужно для загрузки, и выполнить около 5 шагов (вызовы с QNetworkAccessManager). Когда больше нет загружаемых файлов, файл-загрузчик сигнализирует "finished()", который вызывает deleteFinishedThread
и deleteFinishedUploader
, где я это делаю:
QThread *thread = qobject_cast<QThread*>(sender());
if(thread != NULL) thread->deleteLater();
или
FileUploader *fileUploader = qobject_cast<FileUploader*>(sender());
if(fileUploader != NULL) fileUploader->deleteLater();
Предполагается удалить потоки, когда они будут выполнены.
Проблема в том, что каждый раз, когда я запускаю (например) 3 потока, которые имеют 1 файл для загрузки и обработки каждого, количество потоков увеличивается на 8-10. Это означает, что количество потоков составляет от 5 до 100, если несколько раз перезагрузите процесс загрузки.
Что я делаю неправильно? Или моя самая большая проблема, которую я использую "Диспетчер задач Windows", чтобы контролировать это? Я обрабатываю все ответы от QNAM, которые я удаляю, и все, кажется, удаляется, но все же я царапаю себе голову, когда количество строк продолжает увеличиваться...
EDIT: В моем файловом загрузчике я создаю объект (диспетчер) в куче, в котором есть стек QNetworkAccessManager. Когда файловый загрузчик удаляется, он вызывает "deleteLater()" в Менеджере, но он никогда не удаляется. Мы попытались удалить Диспетчер и установить его в NULL, но это дало нам нарушение доступа, так как Менеджер еще не был выполнен (QNetwork.dll сообщила об ошибке, так что это должно быть что-то внутри QNAM, который все еще работает). Время, когда мы не получили нарушение доступа, объект был удален, и количество потоков вернулось к нормальному состоянию. Что может жить внутри QNAM и мешать мне удалять его, когда он выходит за рамки? Должен ли я создать QNAM вместо кучи? На этом этапе не деструкторы вызываются даже при вызове функции deleteLater()...
Также, как уменьшить количество меток?