销毁线程并退出循环

时间:2016-01-07 14:10:46

标签: c++ multithreading qt

我正在创建一个这样的线程:

的main.cpp

    QThread acceptorThread;
    acceptorObject acceptorobject;
    acceptorobject.setupConnections(acceptorThread, simulation);
    acceptorobject.moveToThread(&acceptorThread);

acceptorObject.cpp

void acceptorObject::setupConnections(QThread& thread, Simulation * simulation)
{
    QObject::connect(&thread, SIGNAL(started()), this, SLOT(acceptNewClients()));
}

acceptNewClients()方法在无限循环中工作。此时,如果我关闭我的程序,我会收到错误:

QThread destroyed while thread is still running

我在堆栈中查看了类似的问题,一个人说我需要在完成线程之前打破循环才能摆脱这个bug。他还建议在无限循环中使用一个标志,并在析构函数中发出一个信号,它将改变标志并最终打破循环。当我做这样的事情时,KINDA工作了:

QObject::connect(&thread, SIGNAL(started()), this, SLOT(acceptNewClients()));
QObject::connect(this, SIGNAL(finishThread(bool)), this, SLOT(acceptNewClients(bool)));

然后从析构函数中发出了finishThread(true)信号,所以我直接更改了标志。当然我也改变了插槽签名,所以它不再在新线程中运行了。

析构函数代码:

emit finishThread(true);

this->thread()->quit();
if(!this->thread()->wait(3000))
{
    this->thread()->terminate();
    this->thread()->wait();
}

我该如何使这项工作?

到目前为止我尝试过:

  • 添加将更改标志的新插槽。结果:当我关闭程序时,窗口消失,但进程仍在运行。我认为析构函数会在其发出的信号被占用之前销毁该对象。
  • 在acceptNewClients()槽中创建一个默认的bool参数。结果:它重载了函数,因此一个在不同的线程中运行,第二个尝试更改显然不起作用的标志,因为它们是完全不同的函数。

2 个答案:

答案 0 :(得分:1)

解决方案:

connect(this, SIGNAL(finishThread()), &thread, SLOT(quit()));
connect(this, SIGNAL(finishThread()), this, SLOT(deleteLater()));

在这种情况下更改插槽功能签名毫无意义。 在解构器中,我只是发出了finishThread()信号,仅此而已。

答案 1 :(得分:0)

一种方法是代替在while(true)中执行acceptNewClients而不是

void acceptorObject::acceptNewClients(){
    // do accept new client

    QMetaObject::invokeMethod(this, "acceptNewClients",  Qt::QueuedConnection);
}

本质上是将循环外部化。

另一种选择是让一切都使用信号,QTcpServer(我认为你正在使用)有一个newConnection信号可以连接到。而不是使用waitForNewConnection