了解 Qt 多线程和事件循环
Posted
技术标签:
【中文标题】了解 Qt 多线程和事件循环【英文标题】:Understanding Qt multithreading and event loop 【发布时间】:2018-06-16 15:21:41 【问题描述】:我正在寻求说明以帮助我理解 Qt 4.8 中的 Qt 多线程和事件循环。我还要补充一点,我是一般线程的新手,所以这是我的问题的一部分。
我目前的情况是我有一个 Qt 应用程序,需要经常使用 QTMultiMedia-QAudioOutput 播放声音。我有两个类,MainGui 和 AudioWorker。我希望经常调用 AudioWorker 来“播放()”一个声音。
显然 QAudioOutput 必须有一个 事件循环,因此该过程不会在声音播放之前结束,如果这是在主类中完成的,它将阻止一切。所以我知道线程会有所帮助。
现在,如果我正确理解线程,生成的线程不能比创建它的函数寿命更长,除非它以某种方式分离?因此,如果我在 MainGui 类中收到播放声音的通知,并且我通过插槽连接生成了一个新线程,该线程在 AudioWorker 中调用 play(),一旦我的 MainGui 通知函数结束,带有事件循环的线程不会死吗?如果是这种情况,重点是什么,MainGui 需要事件循环吗?
我肯定错过了什么吗?我是否需要以某种方式分离线程?我在 Qt 文档中没有看到太多关于分离的内容。这整个过程仅仅播放一个简单的声音就显得太过分了。
更新
通过在 play() 函数中创建 QThread 解决了问题。在我发出信号之前,线程不会提前退出。
找到一个隐藏但很好的例子:https://nachtimwald.com/2015/05/02/effective-threading-using-qt/
【问题讨论】:
我认为您可能误解了Qt
文档中的一些 cmets。 QAudioOutput
确实需要一个活动的事件循环才能运行,但它不需要在专用线程上使用其 自己的 事件循环。
嗯,那么也许我的代码错了?我目前正在循环播放 30 次声音,而 gui 开始每个循环播放 2 秒长的音频剪辑。此过程当前阻止我的小部件在播放声音时加载。你是说我可以用另一种方式解决这个问题?
您需要出示您的代码。
@G.M.我已经发布了我的代码。虽然真的很累,但希望我没有错过任何东西
@JavaBeast 如果您找到了答案,请发布步骤并添加答案的必要代码,不要删除产生错误的代码,因为它会使您的问题无法在社区中使用。跨度>
【参考方案1】:
您目前有...
startPlaying();
addWidgetandContainers();
问题是startPlaying
会用明确的QEventLoop
阻塞直到播放完成,从而延迟了对addWidgetandContainers
的调用。
由于您已经将QAudioOutput::stateChanged
连接到您的finishedPlaying
插槽,您可能只需从startPlaying
中删除以下代码...
QEventLoop loop;
do
loop.exec();
while(audioOutput->state() == QAudio::ActiveState);
只要您的主 GUI 线程启动其事件循环(QApplication::exec()
或其他),我认为它应该可以按您的预期工作。
【讨论】:
如果我删除建议我的声音播放一次的代码,并且在 stateChanged 中输入的最后一个状态是 ActiveState。HCI 永远不会打开,但代码永远不会出错。 我认为是因为事件的处理在函数结束时提前终止,因此过早退出使我的代码处于错误状态。 感谢您的帮助,我解决了 QThread 的问题。我从问题中删除了代码,因为我认为它与未来的观众无关,问题更多地旨在理解理论而不是我的具体代码。不幸的是,这会降低您的答案,对此表示歉意。以上是关于了解 Qt 多线程和事件循环的主要内容,如果未能解决你的问题,请参考以下文章
事件循环和线程没有必然关系(就像Windows子线程默认没有消息循环一样),模态对话框和事件循环也没有必然关系(QWidget直接就可以)