此示例用于测试 QThread。主要目标是能够在专用线程中运行一个耗时的阻塞方法,并能够在任何时候终止和重新启动线程。阻止方法是我们无法控制的第 3 方库。我知道 Qt 的文档不鼓励使用 QThread::terminate 但目前我没有看到任何其他方式。
下面是在专用线程中运行所需的代码的伪示例。基本上有一种方法可能需要 10-15 分钟来处理。没有合乎逻辑的地方可以添加 moveToThread 以将亲和性带回 QThread::termination 上的主线程,或执行 processEvent 来处理 QThread::quit() 方法。
void run()
{
// initiate variables
thirdparty lib(var1, var2);
int res = lib.execute(var3, var4, var6);
// handle result and exit
}
在 Windows 7 上使用 Qt 4.7。
运行代码会产生这个输出
Test::doWork thread: QThread(0x219e960)
Test::started thread: QThread(0x239bce8)
Test::doTerminate thread: QThread(0x239bce8)
Test::doWork thread: QThread(0x239bce8)
QObject::moveToThread: Current thread (0x219e960) is not the object's thread (0x239bce8). Cannot move to target thread (0x239bd20)
moveToThread API 在第二次执行 Test::doWork() 方法时失败。这似乎是因为 Test 实例与另一个线程(此时终止)具有亲和力。那我怎样才能改变亲和力呢?
终止和重新启动 QThread 的推荐方法是什么?我需要删除测试实例吗?
编码;
#include <QCoreApplication>
#include <QThread>
#include <iostream>
#include <QDebug>
#include "Worker.h"
#include "Windows.h"
class Test : public QObject
{
Q_OBJECT
QThread* m_thread;
int m_state;
public:
Test() : m_thread(0), m_state(3) { }
public slots:
void doWork()
{
qDebug() << "Test::doWork thread:" << QObject::thread();
if (!m_thread)
{
m_thread = new QThread();
QObject::moveToThread(m_thread);
QObject::connect(m_thread, SIGNAL(started()), this, SLOT(started()));
QObject::connect(m_thread, SIGNAL(finished()), this, SLOT(finished()));
QObject::connect(m_thread, SIGNAL(terminated()), this, SLOT(terminated()));
m_thread->start();
}
}
void started()
{
qDebug() << "Test::started thread:" << QObject::thread();
Sleep(60);
}
void finished()
{
qDebug() << "Test::finished thread:" << QObject::thread();
}
void terminated()
{
qDebug() << "Test::terminated thread:" << QObject::thread();
}
void doTerminate()
{
qDebug() << "Test::doTerminate thread:" << QObject::thread();
QObject::disconnect(m_thread);
m_thread->terminate();
m_thread->wait();
m_thread = NULL;
}
int state()
{
return m_state;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Test test;
test.doWork();
Sleep(10);
test.doTerminate();
Sleep(10);
test.doWork();
return a.exec();
}