暂停 QThread
UpdateThread
is-a QThread
在 UpdateThread::run()
中设置一个调用 slot QTimer
>UpdateThread::tick() 每 t
毫秒。现在,根据某些条件,我需要暂停线程,一段时间后,根据另一个条件,我需要唤醒它。
- 我做
QTimer
事情的方式可以吗?或者我应该将tick
代码移动到run
并每隔t
ms 调用QThread::start()
? - 如何有条件地暂停和唤醒线程
- 或者我应该只是
stop()
QTimer 和start()
后者?
UpdateThread
is-a QThread
That sets up a QTimer
in UpdateThread::run()
that calls slot UpdateThread::tick()
every t
ms. Now based upon some condition I need to Pause
the Thread and after some time based upon another condition I need to wake it up.
- Is the Way I am doing the
QTimer
thing is Okay ? or I should move thetick
code torun
and call theQThread::start()
everyt
ms ? - How can I Pause and wake up the threads conditionally
- Or I should just
stop()
the QTimer andstart()
it latter ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,您不应该在
QThread
子类上定义插槽并从run()
中调用它们 - 插槽将被执行(通过执行跨线程插槽调用)在拥有UpdateThread
实例的线程上下文中(与创建该实例的线程相同,除非您对其调用moveToThread()
),而不是在UpdateThread
表示的线程上下文中。记住这个助记符:相反,在您在
run()
中创建的 QObject 子类上定义插槽>。好吧,抛开这个问题,让我们看一下计时器。
QTimer
文档包含以下内容:(强调我的)特别注意最后一句。
解决方案是跨线程调用
QTimer::start()
和QTimer::stop()
。您可能了解跨线程信号/槽连接。这使用相同的底层机制,该机制在QMetaObject::invokeMethod( )
:现在,这就是从 GUI 线程启动/停止计时器的方法。但您也询问了替代方案。
将
tick()
代码移至run()
中,每隔t
调用UpdateThread::start()
毫秒。这是次优的,因为它会每隔
t
毫秒创建和销毁线程。线程创建仍然是一个昂贵的操作。另外,如果在您下次调用start()
时UpdateThread::run()
尚未完成,您将丢失计时器滴答声。UpdateThread
如上所述。这还不错,但我想说,这不是惯用的多线程。如果计时器触发如此频繁,以至于仅会以某种方式减慢 GUI 线程的速度,那么这是一个很好的解决方案,尽管您也可能会以这种方式丢失计时器滴答声。
QThreadPool
我最喜欢的。将执行
tick()
的代码移至QRunnable::run()
的实现中,并在计时器触发时在线程池中对新的可运行对象进行排队。在这种情况下,计时器最自然地存在于 GUI 线程中,从而避免了如上所述的跨线程方法调用的需要。除非 GUI 线程本身超载,否则您不会错过任何计时器滴答声。您还可以免费缩放系统中的核心数量(如果您不希望这样做,请不要使用 QThreadPool::globalInstance() ,而是创建您自己的实例并调用setMaxThreadCount(1)
).First of all, you shouldn't define slots on your
QThread
subclass and call them from withinrun()
- the slots will be executed (by performing a cross-thread slot invocation) in the context of the thread that owns yourUpdateThread
instance (the same one that created it, unless you calledmoveToThread()
on it), not in the context of the thread represented byUpdateThread
. Remember this mnemonic:Instead, define the slots on a QObject subclass that you create inside
run()
.Ok, with that out of the way, let's have a look at the timer. The
QTimer
documentation contains the following:(emphasis mine) Take particular note of the last sentence.
The solution is to do a cross-thread call of
QTimer::start()
andQTimer::stop()
. You might know about cross-thread signal/slot connections. This uses the same underlying mechanism, which is exposed inQMetaObject::invokeMethod()
:Now, this is how you start/stop the timer from the GUI thread. But you were also asking about alternatives.
Move
tick()
code intorun()
, callUpdateThread::start()
everyt
milliseconds.This is suboptimal, as it would create and destroy threads every
t
ms. Thread creation is still an expensive operation. Also, ifUpdateThread::run()
isn't done by the time you next callstart()
, you'll lose timer ticks.UpdateThread
as outlined above.This isn't too bad, but it's not idiomatic multithreading, I'd say. It's a good solution if the timer fires so often that that alone would slow down the GUI thread somehow, though you might lose timer ticks this way, too.
QThreadPool
My favourite. Move the code that performs
tick()
into an implementation ofQRunnable::run()
, and queue a new runnable on a thread pool whenever the timer fires. In this case, the timer would most naturally live in the GUI thread, avoiding the need for cross-thead method calls as outlined above. Unless the GUI thread itself is overloaded, you won't miss any timer ticks. You also get for free scaling to the number of cores in the system (if you don't want that, don't useQThreadPool::globalInstance()
but create your own instance and callsetMaxThreadCount(1)
).