【问题标题】:Qt: what happens if you send out signals too quickly?Qt:如果你发送信号太快会发生什么?
【发布时间】:2012-04-03 18:29:10
【问题描述】:

情况如下:

  • 您在后台线程中有一个长时间运行的计算。
  • 此计算每 100 毫秒发送一个信号,例如刷新一个 GUI 元素。
  • 假设它发出 100 个这样的信号。
  • 正在重绘的小部件需要超过 100 毫秒才能重绘;假设是 1 秒。

事件循环中会发生什么?信号调用是否“堆积”直到它们全部执行(即 100 秒)?是否有任何“丢弃”事件的机制?

【问题讨论】:

    标签: c++ multithreading qt


    【解决方案1】:

    永远不会丢弃用户事件。如果您将发出的信号事件排队的速度比处理它们的速度快,那么您的事件队列将会增长,直到您耗尽内存并且您的程序将崩溃。不过值得注意的是,如果系统负载过重,QTimer 将跳过超时事件。在某种程度上,这可能有助于调节您的吞吐量。

    您还可以考虑从一个线程向另一个线程发送反馈(也许是确认),并根据消费者线程的落后程度手动调整生产者线程中的时间。或者,您可以使用隐喻的大锤并切换到阻塞队列连接。

    【讨论】:

      【解决方案2】:

      在您的示例中,您可以测量小部件中的绘制时间。例如,如果绘图需要 240 毫秒,那么您可以快速处理接下来的 2 个信号,而无需绘制任何东西。这样信号就不会堆积起来。

      编辑:

      实际上我的解决方案有一个小问题。最后一个信号应该总是导致重绘,否则当计算完成时小部件会显示错误的数据。

      当一个信号被跳过时,可以启动一个单次计时器,例如以 150 毫秒的间隔。当由于信号而完成重绘时,此计时器将停止。所以在最后一次重绘信号之后,这个单次定时器会导致最终状态的绘制。我想这会起作用,但它会相当复杂。

      在计算开始时启动一个简单的计时器来进行重绘很可能是一种更好的方法。如果小部件的绘制耗时较长,可以根据绘制时间动态调整定时器间隔。

      【讨论】:

      • +1。我想我喜欢这种解决方案胜过我提出的任何建议。不过,您可以更进一步,将计算频率与绘图频率完全分离。只需缓存最后发出的值,然后根据计时器重绘。
      • 最佳方法确实取决于具体情况。如果必须不断地进行重绘并且重绘不会花费太多时间,那么使用 QTimer 重绘会很简单,因此是一个很好的解决方案。但是,如果通常根本不需要重绘,并且有时会出现需要大量重绘的变化,那么我提出的解决方案可能会更好。
      • 我在我的解决方案中发现了一个问题,并在答案中添加了一些文本。
      猜你喜欢
      • 2021-01-16
      • 2021-03-11
      • 1970-01-01
      • 2013-09-11
      • 1970-01-01
      • 2011-03-08
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多