51CTO编者按:在做Symbian应用开发和MeeGo应用开发时Q框架是一个统一的开发框架,很多时候需要在QThread的run中new一个QUdpSocket来收发数据.这时,这个socket对象的释放就成了一个麻烦的问题.
如果在thread的析构中直接delete这个socket对象,则会出现如下异常:
- QSocketNotifier: socket notifiers cannot be disabled from another thread
- ASSERT failure in QCoreApplication::sendEvent: “Cannot send events to objects owned by a different thread. Current thread 560cb8. Receiver ” (of type ‘QNativeSocketEngine’) was created in thread a617748″, file kernel\qcoreapplication.cpp, line 349
- Invalid parameter passed to C runtime function.
- Invalid parameter passed to C runtime function.
以下是解决方案:
◆在线程中定义一个线程释放的标识
◆在run()中用while来判断这个标识,以便于结束socket对象.
◆在thread的析构中,设定标识,并使用quit()和wait().
代码如下:
- UdpSocketThread::UdpSocketThread(QObject *parent) :
- QThread(parent)
- {
- this->socket = 0;
- this->needStop = false;
- }
- UdpSocketThread::~UdpSocketThread()
- {
- this->needStop = true;
- quit();
- wait();
- }
- void UdpSocketThread::run()
- {
- socket = new QUdpSocket;
- connect(socket,SIGNAL(readyRead()),this,SLOT(readPendingDatagrams()));
- socket->bind(2234);
- exec();
- while(this->needStop)
- {
- if(this->socket)
- {
- delete this->socket;
- this->socket = 0;
- }
- break;
- }
- }
这个线程对象的释放比较有代表性,应该可以解决很多类似的问题.
另外,方法可能还有其他的,这里只是举了一种而已.
其实,问题的关键就是:线程中创建的对象就必须在线程中释放.
PS:
经shiroki的指正,其实QT有更好的机制来释放对象.那就是deleteLater(). 于是,事情就显得非常简单,请看代码:
- UdpSocketThread::UdpSocketThread(QObject *parent) :
- QThread(parent)
- {
- socket = 0;
- }
- UdpSocketThread::~UdpSocketThread()
- {
- this->socket->deleteLater();
- quit();
- wait();
- }
- void UdpSocketThread::run()
- {
- socket = new QUdpSocket;
- connect(socket,SIGNAL(readyRead()),this,SLOT(readPendingDatagrams()));
- socket->bind(2234);
- exec();
- }
Phone Club——51CTO移动开发线下技术沙龙
本期主题:Android应用开发技术进阶
地点:北京市海淀区中关村南大街30号东联艺术工社
演讲讲师:范怀宇(网易)
【编辑推荐】
- QTreeWidget设计解决没有拖动项问题
- Symbian和MeeGo将统一开发环境 Qt压力很大
- QtCreator:MeeGo开发程序入门手册
- 诺基亚发布Qt 4.6版本 支持多点触摸和手势输入
- 在QT SDK下构建MeeGo Touch开发环境