Qt有很多IO相关的类,比如说QTcpSocket、QFile,总的来说,在Qt的框架内使用,还是非常方便的。
但是用过其他框架IO类的人,可能有一个很不习惯,就是Qt的所有IO类,都不推荐或者不可以跨线程操作,不然就会报错,比如说操作QTcpSocket跨线程调用write接口,就会报错:

socket notifiers cannot be enabled from another thread

要解决这个问题,直观的说就是不要跨线程操作,网上也有很多类似的说明。
这也是有道理的,很多时候真的是设计问题导致的,因为设计失误出现了不应该有的跨线程操作。
当然也可以用信号和槽封装一下,但是这样会涉及很多不必要的代码,我个人觉得也太过于麻烦。
那么我这里就提供一个更简单的方法,对QTcpSocket跨线程调用代码如下:

QMetaObject::invokeMethod( &socket, std::bind( static_cast< qint64(QTcpSocket::*)(const QByteArray &) >( &QTcpSocket::write ), &socket, QByteArray( "xxxx" ) ) );

这个比 socket->write( QByteArray( "xxxx" ) ); 看起来麻烦很多,不过也算是一行代码搞定了。

来分析一下这个 invokeMethod 调用,接口的定义是这样的

bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr)
  • context:表示被调用的函数要在 哪个对象 的生存线程运行
  • function:被调用的函数

主要看这两个,后面都有缺省值,不用管。

在本例中context指定socket,就表示在socket的生存线程运行,这可能是任何线程,取决于你在哪里实例化这个socket。如果填写qApp,就表示指定在主线程运行。
function被赋值了一个std:bind,这是因为write不是槽函数,使用起来还是有点麻烦,不能直接写名字走moc系统。所以要手动用sid::bind把函数给包起来。

关于这个std::bind的3部分:
std::bind( static_cast< qint64(QTcpSocket::*)(const QByteArray &) >( &QTcpSocket::write ), &socket, QByteArray( "xxxx" ) )

static_cast< qint64(QTcpSocket::*)(const QByteArray &) >( &QTcpSocket::write ):QTcpSocket中,叫write的有很多个,所以要依靠 qint64(QTcpSocket::*)(const QByteArray &) 去指定出来是哪一个。这是C++的方法,和Qt无关。
&socket:表示要执行谁的write,有点类似于指针的角色
QByteArray( "xxxx" ):调用write时给的参数


除了IO相关的类,其他有一些Qt的类也不可以跨线程操作,比如说QTimer,也会报错

QObject::startTimer: Timers cannot be started from another thread

按照上面说的调用原理,可以这样写:

QMetaObject::invokeMethod( &timer, std::bind( static_cast< void(QTimer::*)(int) >( &QTimer::start ), &timer, 1000 ) );

对了,start是一个槽函数,所以如果借助moc系统的话,可以这样写(两个写法是等价的)

QMetaObject::invokeMethod( &timer, "start", Q_ARG( int, 1000 ) );

注意!在QMetaObject::invokeMethod配合std::bind使用的时候,5.10.0版本的Qt会有内存泄漏,bug如下:
https://bugreports.qt.io/browse/QTBUG-65462

请注意你的Qt版本,以及bug的修复情况,酌情使用这个方法。

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

  1. Auto.js学习笔记10:实例化自定义对象,在子线程使用JSON.stringify()方法导致报错(已解决)

    申明本人使用的autojs是4.1.1版本 JSON.stringify()使用导致autojs软件直接奔溃退出. 报错核心局部代码 var sendInfoObj = { //对象areaCode ...

  2. winform解决跨线程调用windows窗口控件

    private delegate void Start(int type);private void StartDele(int type) {if (this.InvokeRequired){Sta ...

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

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

  4. 关于PrintQueueCollection()类,跨线程调用错误“线程无法访问此对象,因为另一个线程拥有该对象”

    使用System.Printing.PrintQueueCollection()   纸质打印机获取 _generalPrinters = new PrintQueueCollection(); pu ...

  5. c#中如何跨线程调用windows窗体控件?

    我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来做这个问题,下面我将详细的介绍. 首先来看传统方法: public partial ...

  6. 多线程总结之旅(12):跨线程调用控件的几种方式

    本来是写完线程池就结束多线程总结之旅系列的,但是想想平时在项目中用到线程仅仅不够的,为什么这么说呢?举个例子:我们有一个函数,它的功能就是加载数据,然后绑定到datagridview.现在我们开启一个 ...

  7. 理解Windows窗体和WPF中的跨线程调用

    你曾开发过Windows窗体程序,可能会注意到有时事件处理程序将抛出InvalidOperationException异常,信息为" 跨线程调用非法:在非创建控件的线程上访问该控件" ...

  8. C#跨线程调用窗体控件的问题

    前段时间遇到跨线程调用窗体控件的问题,其实一句话System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;就可以解决,但 ...

  9. C# 跨线程调用控件

    在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应.  同时我们又需要在工作线程中更新UI界面上的控件, 下面介绍几种常用的方法 阅读目录 线程间操作无效 第一种办法:禁 ...

最新文章

  1. 自然语言项目之Python语种检测代码实现
  2. SpringBoot给属性赋值的几种方式以及JSR303校验
  3. Python图片文字识别——Windows下Tesseract-OCR的安装与使用
  4. Java+jquery+jsonp实现跨域
  5. 九度OJ - 题目1481:Is It A Tree?
  6. 《JAVA疯狂讲义》学习笔记第六天
  7. 【开源】一个有趣的文字冒险游戏
  8. 找了个阅读pdf文件语音朗读的软件
  9. 4000亿市值迈瑞医疗的虚火与真金
  10. owncloud 私有云搭建
  11. 猫和老鼠玩象棋,玩了M+N局,猫赢了M局 老鼠赢了N局 NM,而且在整个过程中,猫的得分从来没有超过过老鼠,问共有多少种可能的比赛得分过程
  12. Vue中使用echart实现中国地图统计图
  13. 计算机域名的解释,通俗易懂:域名与IP的关系讲解
  14. proteus仿真的过程中,经常会不小心把示波器关掉,导致无法查看波形。那么如何调出示波器呢?
  15. 第一学历和最高学历哪个更重要?
  16. GetContactInfoUtils(一个获取手机联系人名称,电话,头像的工具类)
  17. 删除流氓软件 Alibaba PC Safe Service
  18. 6月程序员平均工资出炉,这个水平我慕了!
  19. 浮动IP的绑定 、释放、移除
  20. Java 面试/笔试题神整理 [Java web and android]

热门文章

  1. python怎么返回上一步操作_一步一步教你如何用python操作mysql
  2. Banner(轮播)
  3. 最菜的我打卡的第二天
  4. 2019尚硅谷大数据Maven篇一 Maven安装和概念
  5. VC中自定义IE浏览器
  6. C语言入门知识1(零基础新手适用)
  7. android平板打电话,打电话上网不耽误,通话平板你需要吗?
  8. No module named ‘quantopian‘
  9. Python3中的多态 ,鸭子类型
  10. 吴军《数学之美》第二版阅读整理