【问题标题】:Qt Client application halt during waiting response from serverQt 客户端应用程序在等待服务器响应期间停止
【发布时间】:2015-08-27 09:53:03
【问题描述】:

问题:
使用 While 循环检查条件,如果在指定时间内没有得到服务器的响应,则使用计时器。

操作系统: Linux
SDK: QT 5.5

描述:

我已经实现了一个客户端,并且在代码中有一个 while 循环,它不断检查某些条件(“检查机器已启动”)是否为真。当它从机器 Server 收到一些消息时,这种情况会发生变化。当我实现while循环时,它卡在里面并且不会出来。 我在这个论坛上解雇了 Question,有人很好地指出了我的错误,他建议我应该使用 QStateMachine,因为我的 while 循环正在吃掉我所有的资源。

所以在谷歌搜索更多关于状态机的信息时,我偶然发现了 QCoreApplication::processEvents()。当我在我的代码中添加它时,一切都按预期工作,但计时器部分仍然超时。现在我的问题是

1) QStateMachine 和 QCoreApplication::processEvents() 有什么区别?哪个更好。

2) 如何正确使用QTimer,让while循环中的if条件在规定时间内不为真,超时并跳过while循环。

void timerStart( QTimer* timer, int timeMillisecond )
    {
      timer = new QTimer( this );
      connect( timer, SIGNAL( timeout() ), this, SLOT( noRespFrmMachine( ) ) ) ;
      timer->start( timeMillisecond );
    }

    void timerStop( QTimer* timer )
    {
      if( timer )
        {
          timer->stop();
        }
    }

    void noRespFrmMachine( )
    {
      vecCmd.clear();
    }

    void prepareWriteToMachine()
    {
         // Some other code
          //  check if Machine has started we will get response in MainWindow and
          // it will update isMachineStarted so we can check that
          QTimer *timer ;
          timerStart( timer, TIMEOUT_START ); // IS THIS RIGHT??
          while( isMachineStarted() == false  )  // getMachineRunning-> return isMachineStarted ??
            {
              // do nothing wiat for machine server to send machine_started signal/msg
         QCoreApplication::processEvents(); // added this one and my aplication is responsive and get correct result

            }
          if( isMachineStarted() == true )
            {
              // if we are here it mean timer has not expired & machine is runing
              // now check for another command and execute
              timerStop( timer );
              while( vecCmd.size() > 0 )
                {
                  QString strTemp = returnFrontFrmVec();
                  setStoreMsgFrmCliReq( strTemp );
                  reconnectToServer();
                }
            }
        }
    }

【问题讨论】:

  • 你能不能把你的 isMachineStarted() 变成一个信号,在事情启动时发出?这种方式不需要忙着等待调用 processEvents()。
  • 如果我使用 signal ,它将跳过 while 循环条件并执行我不想要的其他命令,除非它被执行。我对进程事件没有问题,我想知道 Qprocess Event 和 QState 机器之间的区别
  • 嗯,QStateMachine 是一个状态机的实现,状态变化可以由信号触发。 ProcessEvents() 是 Qt 事件循环机制的一部分,它将挂起的事件分派到它们的目的地(插槽和事件处理程序)。所以这是两个不同的东西,除了作为 Qt 框架的一部分之外几乎没有共同点。
  • 所以从机器服务器获得响应也是状态变化对吧?所以我可以用 QState Machine 解决上述问题?
  • 得到响应确实可以是触发状态变化的信号。但是目前您的机器通过循环轮询(通过调用isMachineStarted()或检查vecCmd.size)受到质疑,您必须将它们制成信号,以便机器部分在启动时发出started()或dataAvailable()例如,有一个命令要处理。

标签: c++ qt qstatemachine qcoreapplication


【解决方案1】:

timerStop( timer ); 行应该会导致分段错误。 函数timerStart不会改变prepareWriteToMachine()的局部变量timer,所以该变量包含未定义的垃圾。

如果您想更改timerStart 中的外部变量timer,您应该将指向QTimer 的指针传递给该函数:

void timerStart(QTimer**timer, int timeMillisecond)
{
    *timer = new QTimer(this);
    ...
}

顺便说一句,timerStop() 中的检查 if( timer ) 在任何情况下都没有意义,因为 timer 永远不会设置为零。

【讨论】:

  • @Orest,“timerStart 不会更改 prepareWriteToMachine 的局部变量 timer” 我的问题是为什么当我通过引用将变量传递给函数时它会发生变化?为什么你认为它的分段错误?我要求澄清我的疑虑并学习新概念。
  • @samprat,目前您通过值将timer 变量传递给timerStart。所以,prepareWriteToMachinetimer 不会被timerStart 改变。因此,prepareWriteToMachine 的变量 timer 永远不会被初始化,从而导致崩溃。实际上,您可以通过引用传递它。为此,函数timerStart 应使用与符号void timerStart(QTimer*& timer, int timeMillisecond) 定义。在这种情况下,函数timerStart 将直接与外部timer 变量一起使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-02
  • 1970-01-01
  • 2015-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多