Qt moveThread问题

本文探讨了在使用Qt QProcessControl时遇到的线程安全问题,如何正确处理主线程和子线程中的对象构造与析构,以避免程序崩溃。两种解决方案包括主线程内析构和子线程中析构,并提供了相应的代码示例和错误修复方法。
摘要由CSDN通过智能技术生成

在用moveThread时,本意是想避免主界面卡死,把运行时间久的放到子线程里去执行。结果运行时碰到一直崩溃的问题。

实例如下:

extern QProcessControl *g_pProcessCtrl;
#define SAFE_DELETE(e)			if(e!= nullptr){delete e;  e=nullptr;}

QDlgMain::QDlgMain(QWidget *parent)
	: QMainWindow(parent)
{
	m_ui.setupUi(this);

	g_pProcessCtrl = new QProcessControl();
	m_pThread = new QThread();
	g_pProcessCtrl->moveToThread(m_pThread);
	m_pThread->start();

}

QDlgMain::~QDlgMain()
{
	m_pThread->quit();
	m_pThread->wait();
	SAFE_DELETE(g_pProcessCtrl);
}


QProcessControl::QProcessControl(QObject *parent)
	: QObject(parent)
{
	m_pMotion = new MotionControl();
	for (int i = 0; i < StationID_MAX;i++)
	{
		m_pDev[i] = new DeviceControl(m_pMotion,eStationID(i),this);
	}
}

QProcessControl::~QProcessControl()
{
	for (int i = 0; i < StationID_MAX;i++)
	{
		SAFE_DELETE(m_pDev[i]);
	}
	SAFE_DELETE(m_pMotion);
}



原本以为这种写法没问题,结果一运行,QProcessControl析构函数一直崩溃。

报错截图如下:

 报错内容为 不能通过不同的线程来发送对象,创建的对象和析构的对象不在同一个线程里。

经查找资料发现这个问题的本质在于,构造函数在主线程创建,析构函数我也是写在主线程里,但此时对象已经被移到子线程里,主线程这里再来析构函数,就行不通了。

Qt说明书里有一段话:

 如果目标线程为零,那么这个对象及其子对象的所有事件处理都停止了。个人认为应该是要把线程指针析构掉置为null,此时构造的对象就可以在主线程中析构掉。 只需要在safedelete(g_processcontrol)前 加上一句  safedelete(m_pThread),运行正常。 

QDlgMain::~QDlgMain()
{
	m_pThread->quit();
	m_pThread->wait();
	SAFE_DELETE(m_pThread);  //加上这句话
	SAFE_DELETE(g_pProcessCtrl);
	Sleep(100);
}

这是第一种方案:主线程创建的对象,在主线程中析构。

第二种解决方案:主线程创建对象,子线程中析构。

QDlgMain::QDlgMain(QWidget *parent)
	: QMainWindow(parent)
{
	m_ui.setupUi(this);

	g_pProcessCtrl = new QProcessControl();
	m_pThread = new QThread();
	g_pProcessCtrl->moveToThread(m_pThread);
	m_pThread->start();
    
    //这句至关重要
	connect(m_pThread, &QThread::finished, g_pProcessCtrl, &QObject::deleteLater);
}

QDlgMain::~QDlgMain()
{
	m_pThread->quit();
	m_pThread->wait();
    //SAFE_DELETE(g_pProcessCtrl);   由于已经在子线程中析构,所以这里不能再写了
}

可以在构造函数及析构函数里添加获取线程ID,能看出第一种都是在主线程中析构,第二种构造函数的线程ID和析构函数ID是不一样。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值