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();
これらは、完了時にスレッドを削除することを想定しています。
問題は、(たとえば) 1 つのファイルをアップロードして処理する 3 つのスレッドを開始するたびに、スレッド数が 8 ~ 10 増加することです。これは、アップロード プロセスを数回再開すると、スレッド カウントが約 5 から 100 になることを意味します。
私は何を間違っていますか?それとも、「Windows タスク マネージャー」を使用してこれを制御することが最大の問題ですか? 削除した QNAM からのすべての返信を処理しており、すべてが削除されたように見えますが、スレッド数が増え続けると頭を悩ませます...
編集: 私のファイルアップローダーでは、スタックに QNetworkAccessManager を持つヒープにオブジェクト (マネージャー) を作成します。fileuploader が削除されると、Manager で「deleteLater()」が呼び出されますが、削除されることはありません。Manager を削除して NULL に設定しようとしましたが、Manager がまだ完了していないため、アクセス違反が発生しました (QNetwork.dll が問題を報告したため、まだ実行されている QNAM 内の何かである必要があります)。アクセス違反が発生せず、オブジェクトが削除され、スレッド数が正常に戻ったとき。QNAM 内に存在し、範囲外になったときに QNAM を削除できないようにするものは何ですか? 代わりにヒープに QNAM を作成する必要がありますか? この段階では、deleteLater() を呼び出してもデストラクタは呼び出されていません...
また、ハンドル数を減らすにはどうすればよいですか?