我的应用程序中有许多包含QNetworkAccessManager的QOBJECTS。我知道建议只在应用程序中使用一个,但由于我同时进行了超过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()"信号,该信号调用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的所有响应并将其删除,似乎一切都已被删除,但当线程计数继续增加时,我仍感到困惑......
编辑: 在我的文件上传程序中,我在堆上创建了一个对象(管理器),该对象具有栈上的QNetworkAccessManager。当文件上传程序被删除时,它在Manager上调用“deleteLater()”,但它从未被删除。我们试图删除Manager并将其设置为NULL,但由于Manager尚未完成(QNetwork.dll报告了问题,因此必须是QNetworkAccessManager内部仍在运行的某些内容),所以导致了访问冲突。在我们没有遇到访问违规的情况下,对象被删除且线程计数恢复正常。在QNetworkAccessManager中可能存在什么可以阻止我在超出范围时将其删除的内容?我应该在堆上创建QNAM吗?在这个阶段,即使调用deleteLater(),也没有任何析构函数被调用......
另外,如何减少句柄计数?
fileUploaderThread
之前调用QMetaObject::invokeMethod(
。这是确保这些槽在线程循环开始时首先被调用的最佳方法。 - UmNyobeQMetaObject :: invokeMethod
将在事件循环中堆栈起来“init”,并且将首先执行。这就是在QApplication a(argc,argv); MainWindow w; w.show(); return a.exec();
中发生的情况。show()在应用程序甚至循环开始时立即调用。(请参见invoke method文档) - UmNyobe