我已经完成了一个围棋程序,人类可以随时中断软件以命令它运行。基本上,我有一个算法在另一个线程中运行,它每时每刻都有一个可用的“最佳移动”,它会不断改进。
我的问题是:如何正确中断无限循环中的线程?
我已经尝试了一些事情,并决定这样做:
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/