为什么 pyqt5 QThread which 运行 pybind11 c++ lib 仍然挂在我的主 GUI 上?
Why pyqt5 QThread which run pybind11 c++ lib still hang my main GUI?
在我的 PyQt5
程序中,我想开始一个新线程 运行 一些代码:
class SlamThread(QThread):
"""docstring for SlamThread"""
def __init__(self, parent):
QThread.__init__(self, parent)
def setSlam(self, params):
self.params = params
def run(self):
self.slam = Slam()
self.slam.setParams(self.params)
self.slam.start()
其中Slam
是用C++写的,用pybind11转换的
在我的主程序中,代码由 qAction
按钮触发:
def startSlam(self, ...):
params = ...
self.thread = SlamThread(self)
self.thread.setSlam(params)
self.thread.start()
for i in range(10):
print('done')
奇怪的是它确实启动了一个新线程,done
打印在我的 Slam
程序之前。然而,当 Slam
开始时,整个程序挂起,直到 Slam
完成。
在我的C++Slam
代码中,是这样的
int Slam::start()
{
init();
...
startSlam();
return 0;
}
其中 startSlam
需要几分钟才能到达 运行。
根据docs当对象在线程中执行时你必须调用gil_scoped_release和gil_scoped_acquire:
int Slam::start(){
pybind11::gil_scoped_release release;
init();
// ...
pybind11::gil_scoped_acquire acquire;
return 0;
}
或在绑定中:
pybind11::class_<Slam>(mymodule, "Slam")
.def(pybind11::init<>())
.def("setParams", &Slam::setParams)
.def("start", &Slam::start, pybind11::call_guard<pybind11::gil_scoped_release>());
你可以找到完整的测试here
在我的 PyQt5
程序中,我想开始一个新线程 运行 一些代码:
class SlamThread(QThread):
"""docstring for SlamThread"""
def __init__(self, parent):
QThread.__init__(self, parent)
def setSlam(self, params):
self.params = params
def run(self):
self.slam = Slam()
self.slam.setParams(self.params)
self.slam.start()
其中Slam
是用C++写的,用pybind11转换的
在我的主程序中,代码由 qAction
按钮触发:
def startSlam(self, ...):
params = ...
self.thread = SlamThread(self)
self.thread.setSlam(params)
self.thread.start()
for i in range(10):
print('done')
奇怪的是它确实启动了一个新线程,done
打印在我的 Slam
程序之前。然而,当 Slam
开始时,整个程序挂起,直到 Slam
完成。
在我的C++Slam
代码中,是这样的
int Slam::start()
{
init();
...
startSlam();
return 0;
}
其中 startSlam
需要几分钟才能到达 运行。
根据docs当对象在线程中执行时你必须调用gil_scoped_release和gil_scoped_acquire:
int Slam::start(){
pybind11::gil_scoped_release release;
init();
// ...
pybind11::gil_scoped_acquire acquire;
return 0;
}
或在绑定中:
pybind11::class_<Slam>(mymodule, "Slam")
.def(pybind11::init<>())
.def("setParams", &Slam::setParams)
.def("start", &Slam::start, pybind11::call_guard<pybind11::gil_scoped_release>());
你可以找到完整的测试here