我有一个应用程序,可以连续从相机读取图像并将其显示给用户。用户可以调整不同的滑块,例如曝光和阈值,以实时修改图像。我之后也对此图像进行了一系列计算,这有时会使GUI无响应,因此我决定使用线程来划分工作负载。
但是,我无法使其正常工作,有时我会遇到分段错误和一堆断言`GLib-GObject-CRITICAL **:g_object_unref:断言' G_IS_OBJECT(对象)'失败"滑块值更改时的警告或我尝试保存图像(GUI中的保存按钮)时,GUI有时会停止更新图像或冻结,因此您无法移动滑块或按任何按钮。
我尝试做的是在C ++中使用标准的std :: thread,并通过一个插槽将它连接到开始按钮。
QObject::connect(btnStart, SIGNAL(clicked()), this, SLOT(RunStartThread()));
void MainMenu::RunStartThread(){
std::thread t1;
t1= std::thread(&MainMenu::Start,this);
t1.detach();
}
void MainMenu::Start() {
run = true;
window->mngr->ReadCalibration();
window->mngr->InitializeCameras();
while (run) {
window->mngr->CaptureImage();
window->mngr->ProcessImages();
UpdateLabels();
}
window->mngr->Stop();
}
当用户更改滑块值时,它们会更改我的管理器(上面的mngr)中captureImage和ProcessImages使用的变量。我试图在访问变量时使用std :: mutex锁定/解锁,但它没有改变任何东西。我试图找到如何在线进行此操作的示例,但尚未找到具有连续while循环的内容。
当谈到线程时,我是新手,所以请告诉我,我是否以错误的方式接近这一点。
答案 0 :(得分:1)
首先为线程间通信使用singnals和slot。默认情况下,Qt连接在线程之间进行了很好的线程跳转,这样可以避免复杂的同步。
其次,您有三种使用线程的方法:QThread,QRunnable,QtConcurrent::Run(我最喜欢的,因为需要最少量的代码)。
如果QThread
请不要继承它!它是common design mistake。
示例:
SomeClass::~SomeClass()
{
SignalStop();
future.result();
}
void SomeClass::RunStartThread(){
future = QtConcurrent::run(this, &SomeClass::DoOnThread);
}
void SomeClass::DoOnThread()
{
while (ShouldContinueToRun()) {
QImage im1 = CaptureImage();
emit ImageCaptured(im1);
QImage im2 = ProcessImages(im1);
emit ImageProcessed(im2);
}
emit JobCompleted();
}
请注意QObject::connect有最后一个参数,它定义了如果涉及不同的线程,如何执行槽的调用。请参阅此参数使用的documentation of enumeration 因此,默认情况下,Qt检测是否需要跳线。仔细阅读QObject::moveToThread也应该有助于理解问题(请注意,如果对象有父母,则无法将对象移动到不同的线程。)