Einen Thread nicht ordnungsgemäß beenden?

Ich habe eine N-Körpersimulation, die ich parallelisiere. Ich verwende QT, daher habe ich eine benutzerdefinierte QObject-Klasse, die den von mir parallelisierten Prozess enthält. Es wird von einem anderen QObject in einem Thread gesteuert, der nur den Thread verarbeitet. Das Problem ist, dass jedes Mal, wenn ein Objekt mit einem anderen kollidiert, alle Threads angehalten werden müssen, damit sie gelöscht und mit einem anderen Planetensystem neu erstellt werden können.

Hier ist die Quelle der Thread-Handler-Klasse:

#include "threadhandler.h"
#include <QEventLoop>
#include "subprocess.h"
#include <QThread>
#include <iostream>
#include <vector>
#include <thread>
#include <chrono>

ThreadHandler::ThreadHandler(double scopeX, double scopeY)
{
int size = 100;
int idealNum = QThread::idealThreadCount();
int sizeForEach = size/idealNum;

for(int i = 0 ; i< idealNum ;i++){
   SubProcess* tempSub = new SubProcess(i*sizeForEach, (i+1)*sizeForEach, scopeX, scopeY);
   QThread* tempThread = new QThread;
   tempSub->moveToThread(tempThread);
   QEventLoop::connect(tempSub, SIGNAL(finished()), tempThread, SLOT(deleteLater()));
   QEventLoop::connect(tempThread, SIGNAL(started()), tempSub, SLOT(process()));
   QEventLoop::connect(tempThread, SIGNAL(finished()), tempSub, SLOT(deleteLater()));
   QEventLoop::connect(tempSub, SIGNAL(collided()), this,
                       SLOT(refactorObjects()));
   ThreadHandler::threads.push_back(tempThread);
   ThreadHandler::objects.push_back(tempSub);
}
}

void ThreadHandler::process(){
std::cout << ThreadHandler::threads.size() << std::endl;
for(int i = 0; i < ThreadHandler::threads.size(); i++){
    std::cout << "starting " << i+1 << std::endl;
    ThreadHandler::threads.at(i)->start();
}
}

void ThreadHandler::refactorObjects(){
SubProcess::condition = false;
std::this_thread::sleep_for(std::chrono::seconds(1));
for(int i = 0 ; i < ThreadHandler::threads.size() ; i++){
    ThreadHandler::threads.at(i)->terminate();
}
ThreadHandler::objects.clear();
SubProcess::sys.push_back(Body::collide(SubProcess::collidedAr.at(0), SubProcess::collidedAr.at(1)));
SubProcess::sys.erase(std::remove(SubProcess::sys.begin(), SubProcess::sys.end(),
                                  SubProcess::collidedAr.at(0)), SubProcess::sys.end());
SubProcess::sys.erase(std::remove(SubProcess::sys.begin(), SubProcess::sys.end(),
                                  SubProcess::collidedAr.at(1)), SubProcess::sys.end());

int idealNum = QThread::idealThreadCount();
int sizeForEach = SubProcess::sys.size() / idealNum;
for(int i = 0 ; i < idealNum ; i++){
    SubProcess* tempSub = new SubProcess(i*sizeForEach, (i+1)*sizeForEach);
    tempSub->moveToThread(ThreadHandler::threads.at(i));
    ThreadHandler::objects.push_back(tempSub);
    QEventLoop::connect(tempSub, SIGNAL(finished()), ThreadHandler::threads.at(i), SLOT(deleteLater()));
    QEventLoop::connect(ThreadHandler::threads.at(i), SIGNAL(started()), tempSub, SLOT(process()));
    QEventLoop::connect(ThreadHandler::threads.at(i), SIGNAL(finished()), tempSub, SLOT(deleteLater()));
    QEventLoop::connect(tempSub, SIGNAL(collided()), this,
                        SLOT(refactorObjects()));
}

for(int i = 0; i < idealNum; i++){
    ThreadHandler::threads.at(i)->start();
}
std::cout << "refactored" << std::endl;
}

Hier ist die Quelle des Unterprozesses:

#include "subprocess.h"
#include <iostream>

std::vector<Body> SubProcess::sys;
std::vector<Body> SubProcess::collidedAr;
double SubProcess::timeScale;
bool SubProcess::condition = true;


SubProcess::SubProcess(double start, double end, double scopeX, double scopeY){
for(int i = start; i< end; i++){
    SubProcess::sys.push_back(Body::createRandomBody(scopeX, scopeY));
}
this->start = start;
this->end = end;
}
SubProcess::SubProcess(double start, double end){
this->start = start;
this->end = end;
}

void SubProcess::process(){
while(SubProcess::condition){
    for(int i = start; i < end ; i++){
        for(int j = 0; j < SubProcess::SubProcess::sys.size() ; j++){
            if(!(SubProcess::sys.at(i)==SubProcess::sys.at(j))){
                double F = Body::getForce(SubProcess::sys.at(i), SubProcess::sys.at(j));
                if (F!=-1){
                    double dX = SubProcess::sys.at(i).getX()-SubProcess::sys.at(j).getX();
                    double dY = SubProcess::sys.at(i).getY()-SubProcess::sys.at(j).getY();
                    SubProcess::sys.at(i).exertForce(-dY, -dX, F, timeScale);
                } else {
                    SubProcess::collidedAr.clear();
                    SubProcess::collidedAr.push_back(SubProcess::sys.at(i));
                    SubProcess::collidedAr.push_back(SubProcess::sys.at(j));
                    SubProcess::condition = false;
                    emit collided();
                }
            }
        }
        SubProcess::sys.at(i).tick(timeScale);
    }
}
emit finished();
}

Wenn ich es starte, funktioniert es perfekt bis zu dem Punkt, an dem ich eine Kollision erhalte:

starting 1
starting 2
starting 3
starting 4
refactored
refactored
QThread: Destroyed while thread is still running
QThread: Destroyed while thread is still running
QThread: Destroyed while thread is still running
QThread: Destroyed while thread is still running

Was für mich keinen Sinn ergibt, ist, dass die Threads zu Beginn des Refactoring-Prozesses gelöscht werden und dies keinen Fehler verursacht. Aber aus irgendeinem Grund, nachdem die neuen Threads gestartet wurden, beendet sie etwas. Ich habe keine Ahnung, was hier überhaupt los ist. Ich denke, dass ich die Threads nicht ordnungsgemäß anordnete und neu erstellte und dass es eine bessere Methode dafür geben sollte.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage