如何在Qt中停止线程



Qt中停止线程的正确方法是什么?

假设我有一个 worker (LicenseChecker类),我想在 process 成员函数中每 n 秒执行一些操作。我需要无限期地这样做,直到有人中止我的循环。

_worker = new LicenseChecker;
_thread = new QThread;
_worker->moveToThread(_thread);
connect(_thread, SIGNAL(started()), _worker, SLOT(process()));
connect(_worker, SIGNAL(finished()), _thread, SLOT(quit()));
connect(_worker, SIGNAL(finished()), _worker, SLOT(deleteLater()));
connect(_thread, SIGNAL(finished()), _thread, SLOT(deleteLater()));
connect(_worker, SIGNAL(newLicensesActivated(QVector<LicenseInfo>)),
                 this, SLOT(newLicensesActivated(QVector<LicenseInfo>)));
_thread->start();

我该怎么做才能中止它?

我想出的第一个想法是将sleep函数定义为如下:

bool LicenseChecker::sleep(int seconds)
{
    QTime end_time = QTime::currentTime().addSecs(seconds);
    while (QTime::currentTime() < end_time)
    {
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
        QMutexLocker lock(&_abort_sync);
        if (_abort)
        {
            return false;
        }
    }
    return true;
}

并在我的无限循环中检查此函数的返回代码:

while (true)
{
    if (!sleep(5))
    {
        emit finished();
        return;
    }
    // ...
}

然后在MainWindow的关闭事件中,我需要执行以下操作:

_worker->stop();
_thread->wait();

其中stop成员函数只是将数据成员设置为true _abort,但应用程序在这些调用上挂起。

完成此类任务的正确方法是什么?

似乎您从另一个线程(主线程)调用stop(),但工作线程实例位于工作线程中。您可以通过仔细编写类似这样的东西来从另一个线程调用方法来克服这个问题:

void Worker::stop()
{
    // make thread safe
    if(QThread::currentThread() != this->thread())
    {
        this->metaObject()->invokeMethod(this, "stop", Qt::QueuedConnection);
        return;
    }
    REAL CODE HERE ...
}

除此之外,我宁愿使用计时器每n秒触发一次许可证检查。类似的东西(数据库连接检查器的示例):

dbCheckerThread = new QThread(this);
dbCheckerTimer = new QTimer();
dbCheckerTimer->setInterval(CHECKDBCONNECTIONINTERVALL);
dbCheckerTimer->moveToThread(dbCheckerThread);
dbChecker->moveToThread(dbCheckerThread);
connect(dbCheckerTimer, &QTimer::timeout, dbChecker, &DbConnectionChecker::checkConnection);
connect(dbCheckerThread, &QThread::started, dbCheckerTimer, static_cast<void (QTimer::*)(void)>(&QTimer::start));
dbCheckerThread->start();

相关内容

  • 没有找到相关文章

最新更新