了解 Qt 多线程和事件循环

Posted

技术标签:

【中文标题】了解 Qt 多线程和事件循环【英文标题】:Understanding Qt multithreading and event loop 【发布时间】:2018-06-16 15:21:41 【问题描述】:

我正在寻求说明以帮助我理解 Qt 4.8 中的 Qt 多线程和事件循环。我还要补充一点,我是一般线程的新手,所以这是我的问题的一部分。

我目前的情况是我有一个 Qt 应用程序,需要经常使用 QTMultiMedia-QAudioOutput 播放声音。我有两个类,MainGuiAudioWorker。我希望经常调用 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 多线程和事件循环的主要内容,如果未能解决你的问题,请参考以下文章

QT中的线程与事件循环理解

Qt 的线程与事件循环

事件循环和线程没有必然关系(就像Windows子线程默认没有消息循环一样),模态对话框和事件循环也没有必然关系(QWidget直接就可以)

Qt学习笔记8.Qt中的多线程

Qt 阻塞事件循环

Qt 的线程与事件循环