Qt 线程使用的疑惑

十秒耿直拆包选手 2020-07-17 03:03:35
目前学习Qt涉及到QThread的使用,创建新线程后如何在新线程中调用,有些不清楚。希望有大佬能帮忙解释下。

代码:Worker类创建一个worker对象,将worker对象移动到新线程中,随后调动worker的方法。
Worker代码
Work.h
#ifndef WORK_H
#define WORK_H

#include <QObject>

class Work : public QObject
{
Q_OBJECT
public:
explicit Work(QObject *parent = nullptr);

public slots:
void do_work(const QString& parameter);

signals:
void result_ready(const QString& result);

};

#endif // WORK_H


Worker.cpp
#include <QThread>
#include <QtDebug>
#include "work.h"

Work::Work(QObject *parent) : QObject(parent)
{

}

void Work::do_work(const QString ¶meter)
{
qDebug()<< parameter << "start";
qDebug()<< (quint64) QThread::currentThreadId() << endl;
qDebug()<< parameter << "end";
}


具体调用代码:
void Thread_test::create_new_thread()
{
Work* work(new Work());
work->do_work("test");
qDebug()<< "------------------------------------------------" << endl;

// 创建新线程thread,将worker对象移动到thread
QThread* thread(new QThread());
work->moveToThread(thread);


connect(this, &Thread_test::singal_thread, work, &Work::do_work);

thread->start();
// 001
emit singal_thread("emit signal/slot");

// 002
work->do_work("calls do_work");
qDebug()<<"=============================================" << endl;

QThread::sleep(3);
qDebug()<< "in create_new_thread function" << (quint64) currentThreadId() << endl;
qDebug()<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`" << endl;
}


001处通过信号槽调用do_work方法,打印的线程id与主线程不同。
002处直接调用do_work方法,打印的线程id与主线程始终一致。

只有通过信号槽才能真正的在新线程中运行么?
...全文
4341 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
move过去后,槽就在新的线程了。如果不放心,直接用QueuedConnection确保异步连接。
ly1chee 2020-07-18
  • 打赏
  • 举报
回复
在Qt中每个QThread都可开启一个事件循环,而每个QObject有一个线程相关性的东西(thread affinity),每个QObject对象属于创建它的那个线程(你在哪个线程new这个对象,它就属于哪个线程),它接收这个线程分发给它的事件。QObject::moveToThread就是修改这个线程的thread affinity,把它移动到另一个线程,这样它就会从这个新的线程中接收事件。 001处实际上就是向work所属线程thread发了一个事件去调用do_work,这个是标准的做法,也可以不用触发信号的方式,直接QMetaObject::invoke(...,Qt::QueuedConnection) 002处直接调用是有线程安全问题,因为work已经不属于主线程了,它属于thread这个线程,如果直接调用do_work,而do_work中产生了事件(比如启动了一个timer或者有网络请求等等)程序就可能因为线程安全问题crash,所以QObject对象只能在创建它的线程中使用(除非你能保证它不产生事件)。 参考文档Threads and QObjects 另外Multithreading Technologies in Qt这篇文档介绍了,不同场景下使用线程的各种方案。

16,816

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧