c++ - 即使删除线程,线程数也会增加很多

标签 c++ multithreading qt qnetworkaccessmanager

有一个应用程序,其中我有 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 会发出“finished()”信号,它会调用 deleteFinishedThreaddeleteFinishedUploader 我这样做的地方:

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 的所有回复,所有内容似乎都被删除了,但是当线程数不断增加时,我仍然摸不着头脑......

编辑: 在我的文件 uploader 中,我在堆栈上创建了一个对象(管理器),它在堆栈上有一个 QNetworkAccessManager。当文件 uploader 被删除时,它会在管理器上调用“deleteLater()”,但它永远不会被删除。我们试图删除 Manager 并将其设置为 NULL,但这给了我们访问冲突,因为 Manager 尚未完成(QNetwork.dll 报告了该问题,因此它必须是 QNAM 内部仍在运行的东西)。当我们没有遇到访问冲突时,对象被删除并且线程数恢复正常。 QNAM 中有什么可以阻止我在超出范围时删除它?我应该在堆上创建 QNAM 吗?在这个阶段,即使调用 deleteLater(),也不会调用任何析构函数......

另外,如何减少句柄数?

最佳答案

我可能错了,但我认为你的信号有问题:

// 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);

请记住,当多个插槽连接到同一个信号时,它们会按照连接顺序执行。在这里,当fileUploader完成时,它会调用finished(),它会首先调用线程的quit()方法,然后是deleteFinishedUploader( ) 方法。 canceled() 信号也是如此。 但是,与此同时,线程已完成,因此无法对 fileUploader 进行任何事件处理(moveToThread(...) 的结果)。 deleteLater() 需要事件处理,因此您的 fileUploader 将永远不会被删除...

我不是 100% 认为以其他方式安排你的连接会让事情正常进行:deleteLater() 可以被调用并且线程在之后立即退出,无需事件处理。

解决方案可能是重新moveToThread() fileUploader 到主线程,或仍在处理其事件循环的线程。

关于c++ - 即使删除线程,线程数也会增加很多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10184411/

相关文章:

c++ - Qt QList 不附加本地对象

c++ - 即使安装了 qt5,也强制使用 qt4 进行编译

c++ - Intellisense 突然停止工作或在 VS2008 中显示很多不一致

c++ - gcc 优化级别 1 的子选项

python - 空 python 进程挂起加入 [sys.stderr.flush()]

C++ 11 future_status::deferred 不工作

c++ - gcc 和 class 关键字

c++ - 多个可变参数模板函数

python - Flask替代品实现真正的多线程?

c++ - 通过Qt Application约束其他应用程序的窗口大小