我最近在用 C++ 开发基于 Qt 的应用程序时遇到了线程/内存问题,我正在寻找正确的解释。我无法真正发布一个功能完备的示例,因为这需要链接到 Qt 等。但是这个问题在几行简短的代码中得到了非常清楚的解释。
当我点击 gui 上的按钮时,会发生这样的事情:
void MainWindow::onClick(){
std::vector<int> vec;
vec.push_back(0);
dev.connect(vec);
// do some more stuff
}
在这种情况下,dev
是 MainWindow
的成员,并且属于 Device
类类型,表示硬件(或更准确地说,硬件驱动程序) ) 我想与之联系。 connect
的代码是这样的:
void Device::connect(const std::vector<int>& vec){
// do some stuff with vec that takes a long time
}
我遇到的问题是设备驱动程序向我抛出异常,因为它们从 vec
中获取了错误的值。事实上,当我进入 connect
时,数据消失了:在那个范围内 vec
是空内存。我使用 shared_ptr
解决了这个问题。
我的理论是,当我从 GUI 线程调用 dev.connect(vec)
时,Qt 实际上将该调用放在一个单独的线程上。然后,该函数需要很长时间,Qt 决定是时候继续并完成 onClick
(或类似的东西,可能会立即发生),以便到 vec
在 Device::connect
中被处理,它已经超出了范围。考虑到 shared_ptr
在这里节省了一天的时间,这很合适。
所以我的问题是,我对此是否正确?有人可以解释 Qt 的隐式线程行为的细节或者指出一些这样的解释吗?
最佳答案
您要问的是,QT ui 线程是否有可能在某些任务中花费如此长的时间,以至于它被中断,从函数返回,然后尝试从它停止的地方恢复。
答案是否定的。如果一个线程被中断,那么它要么回到原来的位置,要么即将终止。尝试不这样做可能会被病毒扫描程序标记并引入讨厌的错误。
如果您尝试在 UI 线程中执行需要很长时间的操作,那么可能发生的情况是您的 UI 变得无响应,并且操作系统会提示应用程序已变得无响应(因为应用程序不再能够对操作系统发送给它的事件作出 react )。
更有可能的是,当 QT 中发出信号时,无法保证它会立即传递到插槽,因此您最终会遇到您所描述的情况。
shared_ptr “挽救了一天”的事实意味着您不会看到破坏堆栈的情况(好事,它们很难调试);一个简单的堆栈跟踪应该可以回答您的问题。
关于c++ - 从外部对象调用方法时,qt 的 gui 线程是否会在后台生成线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47575166/