c++ - 如何正确中断 QThread 无限循环

标签 c++ qt

我已经完成了一个围棋程序,人类可以随时中断软件以命令它运行。基本上,我有一个算法在另一个线程中运行,它每时每刻都有一个可用的“最佳移动”,它会不断改进。

我的问题是:如何正确中断无限循环中的线程?

我已经尝试了一些事情,并决定这样做:

class MyWorker : public QObject
{
    Q_OBJECT
public:
    MyWorker();
    ~MyWorker();

public:
    ThreadControl * getThreadControl();

public slots:
    void work();

private:
    void endOfComputation();

private:
    ThreadControl * threadControl;
}

请注意,我 don't subclass QThread :

class ThreadControl : public QObject
{
    Q_OBJECT
public:
    ThreadControl();

public:
    bool getAbort();
    Parameter getParameter();
    void setParameter(Parameter & param);

public slots:
    void setAbort(bool b);

private:
    QMutex mutex;
    bool abort;
    Parameter param;
};

最后,无限循环被编码为:

void Myworker::work()
{
    // ...
    forever
    {
        abort = threadControl->getAbort();
        if(abort)
        {
            break;
        }
        // ...
    }
    endOfComputation();
}

然后,你可以猜到,在 main 中,我定期调用 ThreadControl::setAbort(true)

基本上,我只是在主线程中保留一个指向 bool 值的指针,并在需要时切换它。 ( bool 值封装在 ThreadControl 中,因此我可以使用互斥锁正确锁定它)。到目前为止一切顺利,它对我有用......但这对我来说似乎很恶心!切换指向 bool 值的指针听起来像......对我来说糟糕的编程......

问题是网络上的文档主要(完全?)关于生产者和消费者线程,它们在有限的时间后完成,而不是在被要求时完成。没有开发中断线程,这就是我问的原因:有更好的方法吗?

最佳答案

我知道切换标志而不是调用某种专门的方法看起来很难看,但在现实生活中这是最好的方法。专门的方法通常很危险,见 QThread::terminate()例如。一些环境提供了现成的标志,因此您不必添加自己的 bool 值,例如带有 Thread.interrupt() 和 Thread.interrupted() 的 Java。 Qt 没有这样的东西,也许这也很好,因为中断有时在 Java 中有点违反直觉。以 Thread.interrupted()Thread.isInterrupted() 的区别为例。这绝对是违反直觉的。除非您查阅文档,否则您几乎猜不出有什么区别。更糟糕的是,由于其中一个是静态的,您可能会认为 这就是的区别,但事实并非如此。还有,Java中旧式的IO操作不能被中断,而新式的NIO可以,同样没有意义。

有时您可以通过使用其他东西来避免标记。例如,如果一个线程有某种元素的输入队列要处理,您可以使用一个特殊的队列结束元素来指示它应该停在那里。但有时没有方便的地方放这个,那就是当你使用 bool 标志时。

您可以做的唯一一点优化代码的事情就是用 volatile bool 替换互斥锁。但是,这并不能保证内存访问顺序,所以如果你的线程依赖于 volatile write 周围发生的事情,你不应该这样做。或者你可以使用 QAtomicInt 来代替它的内存屏障。但是,如果没有显着的性能影响,使用互斥体就可以了,而且也是最安全的。

我还将循环替换为:

while (!threadControl->getAbort()) {
  // ...

关于c++ - 如何正确中断 QThread 无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4897912/

相关文章:

c++ - Qt 版本不显示图像

c++ - 在确定的时间内生成特定数字的随机序列

c++ - Qt 写入 xml:QIODevice::write (QFile, "D:/logs.xml"): device not open

qt - glClear(GL_COLOR_BUFFER_BIT)后OpenGL无效的帧缓冲操作;

c++ - Qt 资源不工作

c++ - 如何杀死或终止 boost 线程

c++ - QMainWindow::keyReleaseEvent 未按预期工作

c++ - 使用 RStudio 的 R 和 C++

c++ - QAbstractListModel::Data() 方法从未被调用

python - setItemWidget 导致崩溃