c++ - Qt GUI 不能像我预期的那样与 std::thread 一起工作

标签 c++ multithreading qt c++11

我项目的核心独立于 GUI 框架,这就是我更喜欢 std::thread 的原因。但是 Qt 在线程使用时给我一个错误。

The inferior stopped because it received a signal from the operating system.

Signal name: SIGSEGV
Signal meaning: Segmentation fault

//MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <thread>
#include <mutex>
#include <QMainWindow>

namespace Ui { class MainWindow; }

struct Observer
{
    virtual void notify() = 0;
};

class Core
{
public:
    std::thread *run()
        {
            std::thread thread(&Core::runP, this);
            thread.detach();
            return &thread;
        }

    void setObserver(Observer *observer) { _observer = observer; }
    int ii() const { return _ii; }
    void nextIi() { _ii++; }

    void lock()    { _mutex.lock(); }
    bool tryLock() { return _mutex.try_lock(); }
    void unlock()  { _mutex.unlock(); }

private:
    void runP()
        {
            for (int i = 1; i <= 1000; i++) {
                if (i % 10 == 0) {
                    lock();
                    nextIi();
                    unlock();
                    notify();
                }
            }
        }

    void notify() { _observer->notify(); }  //!!!
    Observer *_observer;
    int _ii;
    std::mutex _mutex;
};

struct MwObserver : public Observer
{
    explicit MwObserver(struct MainWindow *mainWindow) { _mainWindow = mainWindow; }
    virtual void notify();

    MainWindow *_mainWindow;
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow() { delete _ui; }
    void upd();

public slots:
    void run() { _core.run(); }

private:
    Ui::MainWindow *_ui;
    MwObserver _observer;
    Core _core;
};

inline void MwObserver::notify() { _mainWindow->upd(); }

#endif

-

//MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    _ui(new Ui::MainWindow),
    _observer(this)
{
    _ui->setupUi(this);
    connect(_ui->pushButtonRun, SIGNAL(clicked(bool)), this, SLOT(run()));
}

void MainWindow::upd()
{
    _core.lock();
    setWindowTitle(QString::number(_core.ii()));
    _core.unlock();
}

最佳答案

这里有多个问题,第一个也是最明显的问题已经被 perencia 注意到了。您正在返回指向堆栈变量的指针。在 C++ 术语中,这是 Not Acceptable 。

其次。崩溃来自于未使用 std::thread,而是竞争条件。 Qt 事件循环不了解您的互斥体,因此您的 setWindowTitle 调用引入了竞争,导致崩溃。 您需要使用 QMetaObject::invokeMethod将函数发布到 Qts 事件循环。

例子: 改变

inline void MwObserver::notify() { _mainWindow->upd(); } 

inline void MwObserver::notify() {
    if(!QMetaObject::invokeMethod(_mainWindow, "upd", Qt::QueuedConnection))
        std::cerr << " Failed to invoke method" << std::endl;
} 

额外包含可能适用

关于c++ - Qt GUI 不能像我预期的那样与 std::thread 一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36778737/

相关文章:

c# - 将(多个)文件复制到多个位置

qt - 在Qt4中,如何检查paintEvent是否由resize触发?

c++ - SFML 极慢/不规则的帧率

c++ - 多线程和 MFC

c++ - 两个线程的公共(public)资源 - 足够同步了吗?

c++ - MacOS 上的 Qbs 静态库

c++ - 使用导入的 makefile 将 Qt Creator .config 添加到 .h

java - JVM 是否为每个对象创建一个互斥锁以实现 'synchronized' 关键字?如果没有,怎么办?

c++ - CUDA 缩减,大阵列的方法

c++ - 你需要只读锁定吗