【问题标题】:Qt Creator crashes when using multiple threads使用多线程时 Qt Creator 崩溃
【发布时间】:2014-10-04 18:25:20
【问题描述】:

我正在编写一个 Qt (5.3) 程序,其中有一个操纵杆测试 UI,但我需要一个单独的线程来进行无限循环,以通过 SDL 寻找操纵杆轴/按钮值的变化。代码的那部分工作正常,因为我可以拥有线程 qDebug() 消息并且它似乎工作。但是在主窗口中,当我尝试打开测试操纵杆 UI 时,程序崩溃了。我已经让测试操纵杆 UI 在没有 JoystickThread 线程的情况下运行分离,它似乎打开得很好。

虽然错误消息不一致 - 有时,我只是得到

程序意外结束。 /home/narendran/QtWorkspace/build-LinkControl-Desktop-Debug/LinkControl 崩溃

这已经出现过一次:

QXcbWindow:未处理的客户端消息:“_GTK_LOAD_ICONTHEMES”

还有几次:

[xcb] 处理队列时序列号未知 [xcb] 很可能这是一个多线程客户端并且 XInitThreads 尚未被调用 [xcb] 中止,抱歉。 星号:../../src/xcb_io.c:274: poll_for_event: 断言 `!xcb_xlib_threads_sequence_lost' 失败。

我发现这很常见,如果 XInitThreads();没有在主函数中运行,但即使在那里,它也会崩溃并出现相同的错误。

ma​​in.cpp

#include <qsplashscreen.h>
#include "linkcontrol.h"
#include "configure.h"
#include <unistd.h>
#include <QApplication>
#include <QPixmap>
#include <QStyle>
#include <QDesktopWidget>
#include "linkports.h"
#include "joystickthread.h"
#include <X11/Xlib.h>

int main(int argc, char *argv[])
{
    XInitThreads();
    QApplication a(argc, argv);

    QPixmap pix(":splash.png");

    QSplashScreen splash(pix);
    splash.show();

    a.processEvents();

    JoystickThread jsThread;
    jsThread.start();

    LinkControl linkcontrol;
    usleep(1000000);
    splash.finish(&linkcontrol);
    usleep(100000);
    linkcontrol.show();

    linkcontrol.setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter,linkcontrol.size(),a.desktop()->availableGeometry()));

    return a.exec();
}

实际线程在 joystickthread.cpp

#include "joystickthread.h"
#include "global.h"
#include "unistd.h"

/* JoystickThread::JoystickThread(int _interval)
{
    this->interval_us = _interval;
} */

void JoystickThread::run()
{
    while(1)
    {
        if(joystick->connected)
        {
            joystick->updateJSData();
            // Check for changed values
            for(int i=0; i<joystick->axis.count(); i++)
            {
                if(joystick->axis.value(i) != joystick->axis_last[i])
                {
                    joystick->axisUpdateEmit(i);
                    // qDebug() << "AXIS: " << i << "\tVALUE: " << joystick->axis.value(i);
                }
                joystick->axis_last[i] = joystick->axis.value(i);
            }
            for(int i=0; i<joystick->button.count(); i++)
            {
                if(joystick->button.value(i) != joystick->button_last[i])
                {
                    joystick->btnUpdateEmit(i);
                    // qDebug() << "BUTTON: " << i << "\tVALUE: " << joystick->button.value(i);
                }
                joystick->button_last[i] = joystick->button.value(i);
            }
        }
        usleep(2500);
    }
}

导致程序崩溃的函数在linkcontrol.cpp

void LinkControl::on_actionJoystick_Test_triggered()
{
    qDebug() << "STARTING CHECK";
    if(!js_test->initialized) {
        qDebug() << "NOT INIT";
        js_test = new TestJoystick();
        js_test->initialized = true;
         qDebug() << "FININSH INIT";
    }
    if(joystick->connected) {
         qDebug() << "SHOWING UI";
        js_test->show();
    } else {
        QMessageBox::critical(this, tr("No Joystick Connected!"), tr("Please connect a joystick first..."));
    }
}

js_testlinkcontrol.h 文件中被声明为 TestJoystick 对象

public:
    explicit LinkControl(QWidget *parent = 0);
    QSlider *portSliders[16];
    QLineEdit *setVals[16];
    SerialTerminal *ser_term;
    TestJoystick *js_test;
    ~LinkControl();

非常感谢!如果您需要更多信息,请告诉我。

【问题讨论】:

    标签: c++ multithreading qt crash x11


    【解决方案1】:

    QThreads 一开始有点难以适应,并且有一些陷阱。

    您应该在 run 函数的顶部构造并连接适当的项目。

    如果你在其他地方这样做,你需要确保你不使用Qt::AutoConnection,而是使用Qt:QueuedConnection

    http://qt-project.org/doc/qt-5/qt.html#ConnectionType-enum

    某些元素只能从“GUI”线程或程序的主线程访问。这是运行QApplication::exec(); 的线程。它有一个传播消息的事件循环。

    查看 Qt 将告诉您的运行时错误的应用程序输出。

    跨越线程边界时,一定要使用信号和槽。

    如果您从该线程外部访问线程类的成员,请务必使用线程同步、实践,例如在对这些成员的所有访问前加上QMutexLocker locker(m_mutex);

    http://qt-project.org/doc/qt-5/threads.html

    正如标题“GUI 线程”所暗示的那样,它是唯一允许做某些事情的线程,例如绘制QPixmaps 和访问QWidgets 的某些部分。

    希望对您有所帮助。

    【讨论】:

    • 出于好奇,这里的哪一个 cmets 解决了您的问题? @NarendranMuraleedharan
    猜你喜欢
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    • 2022-06-10
    相关资源
    最近更新 更多