OpenGL多线程问题排查与解决

图片1

初始问题

运行时发现代码报错,原始代码中没有makeCurrent调用。添加后出现新的错误:
图片1

1
Cannot make QOpenGLContext current in a different thread

问题分析

代码结构

  • 解码线程(ReadThread)读取数据
  • 通过emit发送信号
  • Widget中注册信号与槽
  • 调用updateImage更新
    图片1

调试技巧

  • 单步跳过:不进入函数体,直接到下一行
  • 单步进入:进入函数内部
  • 单步跳出:退出当前函数
    图片1

根本原因

  • updateImage在解码线程中触发
  • OpenGL上下文(Context)在Qt中只能在创建线程中激活(makeCurrent)

解决方案

方案一:Auto模式 + 深拷贝

图片1
优点:

  • 实现简单

缺点:

  • emit(image)默认浅拷贝
  • 可能导致主线程和解码线程访问冲突
  • 解码线程处理速度快于主线程时可能崩溃

改进:

  • 在发送信号时使用image.copy()
  • 避免修改同一份image

方案二:使用阻塞方式

图片1
特点:

  • 控制同时访问
  • 保证线程安全

补充说明

之前使用QPainter没问题的原因:

  • 没有OpenGL的同线程要求
  • 可以使用Direct模式
  • 不需要拷贝image(因为在同一线程)