考虑以下场景:
主线程(Qt主事件循环)中跨线程调用某个函数func(如QtConcurrent::run),在func中又创建了另一个线程,从而将业务逻辑丢到该线程中

class CrossThreadObject(QObject *parent) : QObject(parent)
{Q_OBJECT
...
public slots:void DoSomething(){ //线程C//blockinig }
}class MainThreadObject(QObject *parent) : QObject(parent)
{Q_OBJECT
...void AsyncCall(){//线程A(主线程)QtConcurrent::run(this, &MainThreadObject::Process);}void Process(){//线程B(QtConcurrent线程)thread_ = new QThread;worker_.moveToThread(thread_);  //此处弹出异常 QObject::moveToThread: Current thread  //(0xAAAAAA) is not the object's thread (0xCCCCCC). //Cannot move to target thread (0xAAAAAA) connect(this, &MainThreadObject::Request, &worker_, &CrossThreadObject::DoSomething);  while(1){//blockingemit Request();}}
signals:void Request();
private:CrossThreadObject worker_;QThread *thread_;
}

这里的问题在于QObject对象的所属线程不一致导致moveToThread失败,worker_在线程A中创建,而moveToThread发生在线程B中。改为临时创建即可:

 void Process(){thread_ = new QThread;worker_ = new CrossThreadObject;worker_->moveToThread(thread_);  connect(this, &MainThreadObject::Request, worker_, &CrossThreadObject::DoSomething);  ...}CrossThreadObject *worker_;

官方文档给出了QObject的所属线程规则:Thread Affinity

A QObject instance is said to have a thread affinity, or that it lives in a certain thread. When a QObject receives a queued signal or a posted event, the slot or event handler will run in the thread that the object lives in.
Note: If a QObject has no thread affinity (that is, if thread() returns zero), or if it lives in a thread that has no running event loop, then it cannot receive queued signals or posted events.
By default, a QObject lives in the thread in which it is created. An object’s thread affinity can be queried using thread() and changed using moveToThread().
All QObjects must live in the same thread as their parent. Consequently:
-setParent() will fail if the two QObjects involved live in different threads.
-When a QObject is moved to another thread, all its children will be automatically moved too.
-moveToThread() will fail if the QObject has a parent.
-If QObjects are created within QThread::run(), they cannot become children of the QThread object because the QThread does not live in the thread that calls QThread::run().
Note: A QObject’s member variables do not automatically become its children. The parent-child relationship must be set by either passing a pointer to the child’s constructor, or by calling setParent(). Without this step, the object’s member variables will remain in the old thread when moveToThread() is called.

QObject对象的线程归属(thread affinity),决定了该对象的事件循环运行于所属线程。对象默认属于创建这个对象的线程,可以通过moveToThread改变对象的线程归属。
QObject对象必须跟父对象同一个线程,因此具有父对象QObject对象无法通过moveToThread改变归属,换言之根对象转移线程所属也会影响所有子对象。
QObject A的成员变量并不会跟随A的线程归属。比如A被moveToThread到别的线程了,其成员变量还是属于原来的线程(创建A的线程),除非通过成员变量的构造函数或setParent设定了A为父对象。

Qt跨线程使用moveToThread的注意事项(Cannot move to target thread )相关推荐

  1. QObject::moveToThread: Current thread is not the object`s thread. Cannot move to target thread

    报错:Opencv无法显示图像,报错QObject::moveToThread: Current thread is not the object's thread . Cannot move to ...

  2. connect跨进程 qt_编写 Qt 跨线程异步调用器

    本文使用 Zhihu On VSCode 创作并发布 本文使用 CC BY-NC-SA 4.0 许可协议,转载请注明来源 一.设计背景 众所周知,Qt 的信号槽系统提供了线程安全的跨线程异步执行代码的 ...

  3. Qt笔记-QTcpSocket跨线程调用(官方推荐方法,非百度烂大街方法)

    TCP服务端的经典案例中有个例子,就是当收到TCP客户端连接后,线程池直接开一个线程然后把这个socket指针传到线程里面,依靠新开的线程进程业务处理. 但在Qt里面使用这个方式后,会报一个QTcpS ...

  4. Qt:解决跨线程调用socket/IO类,导致报错的问题(socket notifiers cannot be enabled from another thread)

    Qt有很多IO相关的类,比如说QTcpSocket.QFile,总的来说,在Qt的框架内使用,还是非常方便的. 但是用过其他框架IO类的人,可能有一个很不习惯,就是Qt的所有IO类,都不推荐或者不可以 ...

  5. Qt之线程的使用(moveToThread方式)

    一.本文介绍Qt线程的另一个使用方式,也是Qt官方推荐的方式,即moveToThread方式,楼主的理解就是,就是将这个线程使用方式[Qt之线程的使用(继承QThread重写run函数)]中run函数 ...

  6. Qt多线程编程之moveToThread

    moveToThread方法本质上就是将一个对象放在线程上去执行了 QThread官网文档 moveToThread文档 这里把我认为文档中需要注意的内容摘出来 一定要通过槽函数的形式去调用函数, 要 ...

  7. qt 等待线程结束_实战PyQt5: 128-使用多线程进行并行处理

    多线程是实现并行处理的重要手段,在GUI编程中,经常需要将耗费任务分离,用单独的线程来处理,避免对主线程造成影响(最常见的影响就是会造成主界面无法响应的假死现象).在Qt中,最常用的多线程一般是通过继 ...

  8. Qt创建线程两种方式的区别

    使用QT创建线程有两种方式,方式A使用moveToThread,方式B是直接继承QThread.差异主要在于方式A的槽函数将会在新线程中运行,而方式B的槽函数在旧线程中运行. 结论如下: PS:旧线程 ...

  9. Qt次线程向主程序发送信号收不到的问题

    问题的提出: Qt次线程向主程序发送信号收不到,信号槽connect返回也是true,排查原因如下: 信号或槽函数中的参数用到了自定义类型,如果要在Qt信号槽中使用自定义类型,需要注意使用qRegis ...

最新文章

  1. Mysql 错误 Code: 1093. You can't specify target table for update in FROM clause
  2. mysql中int(15)和varchar(15)
  3. IntelliJ IDEA forMac 如何生成项目的javadoc(API文档)
  4. Linux shell 脚本SDK 打包实践, 收集assets和apk, 上传FTP
  5. 【Matlab/C/Python/VB/...】代码复制到word时如何变成彩色的
  6. jQuery学习之一---选择器
  7. axure中备注线_Axure教程资料
  8. 这是用过的最差树形插件
  9. 关于visual studio 2005的中文版下载(最新详细下载点)
  10. java中数据库查询_在java中对数据库查询
  11. otool 和 install_name_tool
  12. 插值(五)Bicubic interpolation(双三次插值)
  13. html5指纹特效,小米11指纹特效很神奇这样设置
  14. 11个销售心理学方法,帮你搞定客户!
  15. QWebEngineView右键菜单翻译
  16. Android输入法架构学习总结
  17. GPT系列-1-ChatGPT的理解
  18. 使用php读取大量列的excel数据
  19. 滴水逆向——PE导出表
  20. 基于多模态数据挖掘算法matlab,多模态生物数据分析与挖掘研究

热门文章

  1. VB基础版版务处理_20050827
  2. Delphi下POS打印机,控制开钱箱,客显,顾客显示屏,小票打印机
  3. 三电平LLC matlab/simulink仿真 控制策略
  4. windows live mail error message
  5. GoDaddy的成功不是偶然
  6. 将时谐电磁场引入工程电磁场的意义_《工程电磁场》复习提纲
  7. 不同粒径大小的金纳米粒子|单分散小粒径金纳米颗粒|黄色纳米颗金粒粒径2nm
  8. Ubuntu 安装 wine (使用windows下软件)
  9. 极几何,本质矩阵,基础矩阵,单应矩阵,相机投影矩阵
  10. 云计算项目实训教学解决方案