Имейте приложение, в котором у меня есть 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). Когда нет больше нет элементов для загрузки, то fileUploader сигналы «закончил()», который вызывает 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() ...
Также, как уменьшить количество элементов управления?
добавил щедрость. на ваш вопрос нужна какая-то любовь ... – UmNyobe
ой, спасибо. вы сделали свой день :) – chikuba
один комментарий: если вы все еще используете их, вызовите 'QMetaObject :: invokeMethod (' перед запуском 'fileUploaderThread'. Это лучший способ обеспечить, чтобы эти слоты вызывались при первом запуске цикла потока. – UmNyobe