如何在Qt GUI中使用线程

时间:2016-05-24 07:04:21

标签: c++ multithreading qt

我有一个应用程序,可以连续从相机读取图像并将其显示给用户。用户可以调整不同的滑块,例如曝光和阈值,以实时修改图像。我之后也对此图像进行了一系列计算,这有时会使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循环的内容。

当谈到线程时,我是新手,所以请告诉我,我是否以错误的方式接近这一点。

1 个答案:

答案 0 :(得分:1)

首先为线程间通信使用singnals和slot。默认情况下,Qt连接在线程之间进行了很好的线程跳转,这样可以避免复杂的同步。

其次,您有三种使用线程的方法:QThreadQRunnableQtConcurrent::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也应该有助于理解问题(请注意,如果对象有父母,则无法将对象移动到不同的线程。)