创建C ++ std :: thread时QT GUI崩溃

时间:2018-12-24 23:17:38

标签: c++ multithreading qt user-interface

为什么我用std :: thread创建新线程后GUI崩溃?我收到的唯一输出是:

  

传递给C运行时函数的参数无效。
  无效的参数传递给C运行时函数。

仅这两行和来自Windows的消息,即应用程序已请求运行时以一种异常方式终止它。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QBoxLayout>
#include <QPushButton>
#include <thread>
#include <iostream>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QPushButton* button = new QPushButton;
    button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    QGridLayout *layout = new QGridLayout;
    connect(button, SIGNAL(released()), this, SLOT(buttonSignal()));
    layout->addWidget(button);
    centralWidget()->setLayout(layout);
}

void foo(){
    //want to do stuff in here
}

void MainWindow::buttonSignal(){
    std::thread thread (foo);
}

MainWindow::~MainWindow()
{
    delete ui;
}

3 个答案:

答案 0 :(得分:3)

问题是您的thread对象在MainWindow::buttonSignal中是本地对象,并且在销毁之前没有加入,这是导致std::terminate being called的运行时错误。

您可以使线程对象成为MainWindow类的成员,然后在MainWindow::buttonSignal中启动线程

void MainWindow::buttonSignal(){
    thread = std::thread(foo);
}

这将创建一个临时std::thread,将使用move assignment进行移动。

别忘了在销毁之前显式加入线程:

MainWindow::~MainWindow()
{
    delete ui;
    if (thread.joinable())
        thread.join();
}

当然,不要忘记正确同步线程之间的所有通信。

答案 1 :(得分:0)

由于thread方法退出后buttonSignal变量被破坏,因此您应该从变量中分离线程。

void MainWindow::buttonSignal(){
    std::thread thread (foo);
    thread.detach();
}

答案 2 :(得分:0)

您还可以考虑将std :: async与lambda函数一起使用,以在单独的线程中执行次要任务。然后,您可以从中初始化一个std :: future类成员,以获取结果和通知。 另外,还有QtConcurrent框架中的QFuture和QFutureWatcher。