使用多个线程时,Qt Creator崩溃

时间:2014-10-04 18:25:20

标签: c++ multithreading qt crash x11

我正在编写一个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]中止,对不起。   star:../../ src / xcb_io.c:274:poll_for_event:断言`!xcb_xlib_threads_sequence_lost'失败。

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

的main.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_test linkcontrol.h 文件中声明为 TestJoystick 对象

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

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

1 个答案:

答案 0 :(得分:0)

QThread对于最初习惯来说有点棘手,并且有一些困难。

您应该在运行功能的顶部构建和连接适当的项目。

如果您在其他地方执行此操作,则需要确保不使用Qt::AutoConnection,而是使用Qt:QueuedConnection

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

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

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

跨越线程边界时,请务必使用信号和插槽。

如果您从该线程外部访问线程类的成员,请务必使用线程同步和实践,例如使用QMutexLocker locker(m_mutex);为这些成员添加所有访问权限。

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

正如标题&#34; GUI线程&#34;所暗示的那样,它是唯一允许执行某些操作的线程,例如绘制QPixmap和访问QWidget的某些部分第

希望有所帮助。