使用 Qthread-Qt5 创建新线程
creating new thread using Qthread-Qt5
我正在尝试创建一个应该在后台运行的新线程gpsthread
,并存储值。
class gpsthread: public QThread{
Q_OBJECT
private:nrega_status_t status2;
public:
explicit gpsthread(QObject *parent = 0):QThread(parent) {
// QTimer *t = new QTimer(this);
// connect(t, SIGNAL(timeout()), this, SLOT(processgps()));
// t->start(10000);
}
void run(){
qDebug()<<"inside gps threadn";
QTimer *t = new QTimer(this);
connect(t, SIGNAL(timeout()), this, SLOT(processgps()));
t->start(10000);
}
public slots:void processgps(){
int status2;
status2=gps_management();
}
};
我的主要课程是概览。
int main(int argc, char *argv[])
{
QString file = "qml/main.qml";
QApplication app(argc, argv);
TranslationTest myObj;
QuickView view;
subthread object;
gpsthread obj;
gprsthread gprs;
view.rootContext()->setContextProperty("rootItem", (QObject *)&myObj);
obj.start();
//from subthread
QObject::connect(&object, SIGNAL(batterytoqml(QVariant,QVariant)),item, SLOT(frombattery(QVariant,QVariant)));
QObject::connect(&gprs, SIGNAL(gprstoqml(QVariant)),item, SLOT(fromgprs(QVariant)));
return app.exec();
}
我也试过这个
class gpsthread: public QThread{
Q_OBJECT
private:nrega_status_t status2;
public:QTimer* t;
explicit gpsthread(QObject *parent = 0):QThread(parent) {
// QTimer *t = new QTimer(this);
// connect(t, SIGNAL(timeout()), this, SLOT(processgps()));
// t->start(10000);
}
void run(){
qDebug()<<"inside gps threadn";
t = new QTimer(this);
connect(t, SIGNAL(timeout()), this, SLOT(processgps()));
t->start(10000);
exec();
}
public slots:void processgps(){
int status2;
status2=gps_management();
}
};
但它给出了错误说
QObject: Cannot create children for a parent that is in a different thread
如果我在构造函数中创建对象,那么它也会产生相同的错误,因为该对象将在主线程中创建。如何解决这个问题?
不建议使用从 QThread 继承。QThread 是一个运行事件循环的完整类,这通常是您需要的。该文档建议使用从 QObject 继承并在插槽中工作的工作器对象。工作线程被移动到 QThread 中。发送连接的信号时,插槽将在正确的线程中运行。
class gpsworker: public QObject
{
Q_OBJECT
public:
explicit gpsworker(QObject *parent = 0):
QObject(parent)
{}
public slots:
void processgps() {
qDebug() << "processgps()" << QThread::currentThreadId();
}
}
void OwnerClass::startWorker() {
QTimer *timer = new QTimer(this);
QThread *thread = new QThread(this);
this->worker = new gpsworker();
this->worker->moveToThread(thread);
connect(timer, SIGNAL(timeout()), this->worker, SLOT(processgps()) );
connect(thread, SIGNAL(finished()), this->worker, SLOT(deleteLater()) );
thread->start();
timer->start();
}
如果您希望计时器也存在于另一个线程中,QTimer::start
是一个插槽。
QObject: Cannot create children for a parent that is in a different thready
是因为run()
中的t = new QTimer(this)
是在子线程中创建一个对象,但this
gpsthread
点在主线程中。一个简单的解决方案是在没有父级的情况下t = new QTimer()
并删除析构函数中的计时器。下面是一个示例:
class gpsthread : public QThread {
Q_OBJECT
public:
explicit gpsthread(QObject *parent = 0):
QThread(parent)
,timer(NULL) {
qDebug() << "Parent thread" << QThread::currentThreadId();
}
~gpsthread() {
quit();
wait();
delete timer;
}
protected:
void run() {
qDebug() << "Inside gps thread" << QThread::currentThreadId();
timer = new QTimer; // no parent
connect(timer, SIGNAL(timeout()), this, SLOT(processgps()));
timer->start(1000);
exec();
}
public slots:
void processgps() {
qDebug() << "processgps()" << QThread::currentThreadId();
}
private:
QTimer *timer;
};
很快你会发现控制台打印:
Parent thread 0x3b28
inside gps thread 0x3f10
processgps() 0x3b28
processgps() 0x3b28
processgps() 0x3b28
processgps() 0x3b28
这意味着processgps()
在您的子线程中不起作用。这是因为此插槽是主线程中gpsthread
的成员。一个简单的解决方案是直接调用processgps()
并使用sleep()
作为计时器:
class gpsthread : public QThread
{
Q_OBJECT
public:
explicit gpsthread(QObject *parent = 0):
QThread(parent)
, abort(false) {
qDebug() << "Parent thread" << QThread::currentThreadId();
}
~gpsthread() {
abort = true;
wait();
}
protected:
void run() {
while(!abort) {
sleep(1);
processgps();
}
}
public slots:
void processgps() {
qDebug() << "processgps()" << QThread::currentThreadId();
}
private:
bool abort;
};
这不是一个好的解决方案,一种建议的方法是创建一个worker来完成所有工作,然后使用QObject::moveToThread((,如QThread文档中所述
相关文章:
- 在挂钩启动新线程时解除挂钩进程
- 如何检查第三个 API 是否在 Linux 中为 c/c++ 程序创建了一个新线程?
- C++中的多线程:连接线程的正确方法
- 是否需要在 Timer.5 boost::asio 教程中运行新线程?
- SetTimer (带有回调函数)是否通过启动新线程来工作?
- Zmq 上下文 - 我应该在新线程中创建另一个上下文吗?
- 函数如何在不这样做的情况下在新线程上运行"as if"?
- 从 VS2013 到 VS2017 std::async 不会启动新线程
- 从传递给新线程C++的矢量中删除项目
- c++ 从成员函数创建新线程并移动对象和整个对象
- 在新线程C++中发送 http 请求
- 在新线程中访问移动的 std::string
- 使用新线程在类似于 Scott Meyer 的单例习惯用法的实现中实例化单例是否安全?
- Winapi:在类成员功能上创建新线程 - 不兼容的参数类型
- 使用新线程池而无需重新启动的新线程池后,Jemalloc的内存大大增加
- C++ std::async 不会生成新线程
- 如何在 Linux 上强制 g++ 在协程切换线程时更新线程指针(对于 TLS)
- 一旦另一个线程完成,就会生成一个新线程
- 只在前一个线程完成时创建一个新线程
- 创建新线程时在lambda内部使用unique_ptr的线程安全性