QThread - 如何阻止工人?

Dib*_*ibo 2 c++ qt

我正在读取我应该使用worker对象并通过moveToThread将其移动到线程而不是直接从QThread继承.但我找不到解决方案如何在我的对象工作者中停止循环.例如,我有测试循环:

void CollectionWorker::doWork()
{
    for (int i = 0; i < 10; ++i) {
        sleep(1);
        emit ping(i);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我将此对象移动到线程:

worker->moveToThread(mTh); 
Run Code Online (Sandbox Code Playgroud)

这工作正常.但是当我调用mTh.quit()时,线程正在等待,直到doWork中的循环结束.当我从继承的QThread然后直接在每次循环,我可以检查线程状态,并在thred完成破环,但不知道如何做到这一点的工人对象.我可以在worker对象中创建一些标志并从主线程切换它吗?或者我可以找到线程所有者并检查它的状态吗?或者在启动线程之前更好,在工作对象中设置线程指针,然后检查状态?什么是最好的线程安全解决方案?

问候

Cha*_*ert 6

如果有任何运行,则在线程对象上调用quit()或exit()将简单地结束线程的事件循环.但正如你正确指出的那样,原来的问题仍然存在.如果worker函数已经由事件循环执行并且是具有forever构造的长时间运行的函数,该怎么办?对quit()或exit()的调用只会等到worker函数返回.

除了使调用者可以使用公共函数之外,还可以建议几种方法,这将改变内部标志.

  • 在您的工人类中提供终止信号和插槽.事如下.

    signals:
        void signalTermination();
    public slots:
        void setTerminationFlag();
    private:
        QMutex mutex;
        bool terminationRequested;
Run Code Online (Sandbox Code Playgroud)

你的插槽看起来像什么.

void setTerminationFlag()
{
    QMutexLocker locker(&mutex);
    terminationRequested = true;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以在永久循环的每次迭代中检查doWork函数中的变量.

mutex.lock();
if(terminationRequested)
{
    //break from loop and effectively doWork function
}
mutex.unlock();
Run Code Online (Sandbox Code Playgroud)

使用信号和槽而不是普通成员函数的原因之一是,如果您的worker函数在同步代码块中执行一些长时间运行的任务,则公共函数将保持阻塞状态,直到它获得同步对象的访问权限.如果公共终止方法的调用线程是UI线程,则可能会产生负面影响.

  • 如果您使用Qt 5.2以上,那么另一种简洁明了的方法

使用QThread的requestInterruption()方法.此方法在线程对象中设置一个顾问标志,您可以通过doWork()函数中的isInterruptionRequested()函数调用来检查该标志.请参阅QThread :: isInterruptionRequested文档中给出的以下代码段.

void long_task() {
    forever {
        if ( QThread::currentThread()->isInterruptionRequested() ) {
            return;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你也可以在这里直接调用quit()来结束线程的事件循环.