2012-04-03 45 views
4

这种情况:Qt:如果你发送信号太快会发生什么?

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

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

回答

4

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

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

3

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

编辑:

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

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

启动一个简单的计时器来做计算开始时的重绘很可能是一个更好的方法。如果小部件的绘图需要很多时间,则可以根据绘制时间动态调整定时器间隔。

+0

+1。我想我比我提出的任何东西都更喜欢这种解决方案。尽管如此,您可以进一步将计算频率与绘图频率完全分离。只需缓存最后发出的值,然后根据计时器重新绘制。 – cgmb 2012-04-03 20:54:17

+0

最好的方法确实取决于案例。使用QTimer重新绘制将变得简单,因此是一个很好的解决方案,如果重绘必须不断进行并且重画不需要太多时间。但是如果通常根本不需要重新绘制,然后有时会出现突发变化,需要进行相当大的重绘,那么我提出的解决方案可能会更好。 – 2012-04-03 21:11:03

+0

我在我的解决方案中发现问题,并在答案中添加了更多文本。 – 2012-04-03 21:29:14

相关问题