• 7832阅读
  • 8回复

[提问]QT新手请教while循环与界面死掉 [复制链接]

上一主题 下一主题
离线zhangyusnake
 
只看楼主 倒序阅读 楼主  发表于: 2012-01-14
我是做硬件程序出身。刚接触软件。

现在用qt写了一个上位机。现在有个小功能出问题
这个功能的步骤如下:
1.发送一个数据帧。开始计数。
2.超时后没有收到响应帧,重新发送。
3.3次超时后或者收到相应帧后退出。

  1. ctrlUdpTx.writeDatagram(tmpTx,QHostAddress(Unit[unit].ip),TX_PORT);
  2.   setTimer.start(SET_TIMEROUT);
  3.   receiveSetAck = false ;
  4.   setTxCnt   = 1;
  5.   unsigned char tmpCnt = 1;
  6.   forever {
  7.     if(tmpCnt != setTxCnt)  {
  8.       ctrlUdpTx.writeDatagram(tmpTx,QHostAddress(Unit[unit].ip),TX_PORT);
  9.       tmpCnt = setTxCnt ;
  10.     }
  11.     if(receiveSetAck || (setTxCnt >= 3) ) {
  12.       if(receiveSetAck) trayShowMsg(tr("set ok"));
  13.       else              trayShowMsg(tr("set timeout"));
  14.       break;
  15.     }
  16.   }
代码如上,但是会导致界面死掉。

后来想到使用线程。因为刚学习一周,很多细节不了解。
后来想到使用线程,
将这部分代码移植到线程class b中;
在Class a使用signalslot绑定线程class b中的函数之后,如何告诉class b结束呢?(还是使用signal slot再绑定一个函数吗?)
在线程class b中可以使用forever循环吗?


dsf
离线XChinux

只看该作者 1楼 发表于: 2012-01-14
1. 把这段代码放到一个另一个线程中去(比如class b)
2. 循环部分,采用事件循环,即每次处理完数据后调用QTimer::singleShot()来进行下次处理,这样就能进行消息循环了,就能与class a使用信号/槽进行通信了.
二笔 openSUSE Vim N9 BB10 XChinux@163.com 网易博客 腾讯微博
承接C++/Qt、Qt UI界面、PHP及预算报销系统开发业务
离线zhangyusnake
只看该作者 2楼 发表于: 2012-01-14
代码修改成如下之后界面没有死掉,但是后台一直在打印"thread",这个时候已经收到响应了。
这个线程是在一个函数中调用:
void set()
{
  chanThread = new SetChanThread();
  chanThread->unit   = unit  ;
  chanThread->ip     = ip    ;
  chanThread->start();
}


  1. void SetChanThread::run()
  2. {
  3.   udpChSetThread() ; //发送一帧数据,然后seTxCnt++
  4.   while((!receiveSetAck) && (setTxCnt < 3)) { //接收到响应或者发送次数超过3次,退出
  5.     qDebug()<<"thread";
  6.     QTimer::singleShot(SET_TIMEROUT,this,SLOT(udpChSetThread()));
  7.   }
  8.   setTxCnt = 0;
  9. }


PS:
receiveSetAck 是thread的成员,在主线程中判断是否接收到响应,如果接收到响应,设置成true
通过调试发现这个receiveSetAck没有成功。


void get()
{
  if(rx == ID) chanThread->receiveSetAck = true;
}

不知道什么原因


dsf
离线XChinux

只看该作者 3楼 发表于: 2012-01-14
1、不需要那个while()循环了,
2、末尾加个exec()来代替while()循环同时提供消息循环功能以处理信号、槽。
二笔 openSUSE Vim N9 BB10 XChinux@163.com 网易博客 腾讯微博
承接C++/Qt、Qt UI界面、PHP及预算报销系统开发业务
离线zhangyusnake
只看该作者 4楼 发表于: 2012-01-14
回 3楼(XChinux) 的帖子
但是我要实现发生三次怎么做呢,
    void SetChanThread::run()
    {
        QTimer::singleShot(SET_TIMEROUT,this,SLOT(udpChSetThread()));
        exec()
    }

只能发送一次。

谢谢指教!
dsf
离线XChinux

只看该作者 5楼 发表于: 2012-01-14
在udpChSetThread()里再调用一次QTimer::singleShot(....)
在里面通过成员变量计次数,决定是否继续循环。
二笔 openSUSE Vim N9 BB10 XChinux@163.com 网易博客 腾讯微博
承接C++/Qt、Qt UI界面、PHP及预算报销系统开发业务
离线zhangyusnake
只看该作者 6楼 发表于: 2012-01-15
回 5楼(XChinux) 的帖子
代码如下,已经可以了。但是还有个问题,就是每次new的 SetChanThread,内存释放不掉。我用top查看内存每次都增加。
每执行一个test就增加一部分。如何能是放掉线程的资源?

  1. void test()
  2. {
  3.   chanThread = new SetChanThread();
  4.   connect(chanThread, SIGNAL(finished()), chanThread, SLOT(deleteLater()));
  5.   chanThread->start();
  6. }
  7. void SetChanThread::run()
  8. {
  9.   receiveSetAck = false ;
  10.   setTxCnt = 0;
  11.   QTimer tmpTimer1;
  12.   connect(&tmpTimer1,SIGNAL(timeout()),this,SLOT(udpChSetThread()));
  13.   udpChSetThread() ;
  14.   tmpTimer1.start(SET_TIMEROUT);
  15.   exec();
  16. }
  17. void SetChanThread::udpChSetThread()
  18. {
  19.   if((!receiveSetAck)&&(setTxCnt<3)) {
  20.     ctrlUdpTx.writeDatagram(tmpTx,QHostAddress(ip),AVB_TX_PORT);
  21.     ++setTxCnt ;
  22.   }
  23. }





dsf
离线zhangyusnake
只看该作者 7楼 发表于: 2012-01-15
Re:回 5楼(XChinux) 的帖子
引用第6楼zhangyusnake于2012-01-15 11:13发表的 回 5楼(XChinux) 的帖子 :
代码如下,已经可以了。但是还有个问题,就是每次new的 SetChanThread,内存释放不掉。我用top查看内存每次都增加。
每执行一个test就增加一部分。如何能是放掉线程的资源?
[code]void test()
{
.......



udpChSetThread()里面加上
  else
  {
    exit();
  }

虚拟内存会增加个30m之后不再增加。不确定这30m怎么增加的。

dsf
离线unizii

只看该作者 8楼 发表于: 2012-01-22
加入qApp->processEvent();
快速回复
限100 字节
 
上一个 下一个