简体   繁体   English

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

[英]Qt Creator crashes when using multiple threads

I'm writing a Qt (5.3) program which has a joystick test UI in it, but I need a separate thread for an infinite while loop looking for joystick axis/button value changes through SDL. 我正在编写Qt(5.3)程序,其中包含操纵杆测试UI,但是我需要一个单独的线程用于无限while循环,以通过SDL查找操纵杆轴/按钮值更改。 That part of the code is working fine as I can have the thread qDebug() messages and it seems to work. 代码的这一部分工作正常,因为我可以使用线程qDebug()消息,并且似乎可以正常工作。 But from the main window, when I try to open the test joystick UI, the program crashes. 但是从主窗口中,当我尝试打开测试操纵杆UI时,程序崩溃了。 I've had the test joystick UI running separation WITHOUT the JoystickThread thread and it seems to open up fine. 我已经在没有JoystickThread线程的情况下使测试操纵杆UI运行分离,并且似乎可以正常运行。

The error messages are inconsistent though - some times, I just get 错误消息虽然不一致-有时,我只是得到

The program has unexpectedly finished. 该程序意外完成。 /home/narendran/QtWorkspace/build-LinkControl-Desktop-Debug/LinkControl crashed / home / narendran / QtWorkspace / build-LinkControl-Desktop-Debug / LinkControl崩溃

This has shown up once: 这已经出现一次:

QXcbWindow: Unhandled client message: "_GTK_LOAD_ICONTHEMES" QXcbWindow:未处理的客户端消息:“ _ GTK_LOAD_ICONTHEMES”

And a few other times: 还有其他几次:

[xcb] Unknown sequence number while processing queue [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called [xcb] Aborting, sorry about that. [xcb]处理队列时未知的序列号[xcb]这很可能是多线程客户端,尚未将XInitThreads称为[xcb]正在中止,对此感到抱歉。 star: ../../src/xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed. 星号:../../src/xcb_io.c:274:poll_for_event:断言`!xcb_xlib_threads_sequence_lost'失败。

I found that this was common if XInitThreads(); 我发现如果XInitThreads();这很常见。 is not run in the main function, but even with it on there, it crashes with the same error(s). 不是在主函数中运行,但是即使在主函数上运行,它也因相同的错误而崩溃。

main.cpp 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();
}

The actual thread is in joystickthread.cpp 实际线程在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);
    }
}

The function that causes the program to crash is in linkcontrol.cpp 导致程序崩溃的函数在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..."));
    }
}

Where js_test is declared as a TestJoystick object in the linkcontrol.h file 其中js_testlinkcontrol.h文件中声明为TestJoystick对象

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

Thank you very much! 非常感谢你! Please let me know if you need anymore information. 如果您需要更多信息,请告诉我。

QThread s are a little tricky to get used to initially, and have their share of gotchas. QThread有些棘手,并且有一些麻烦。

You should construct and connect appropriate items at the top of your run function. 您应该在运行功能的顶部构造并连接适当的项目。

If you do it other places, you need to make sure that you don't use Qt::AutoConnection , but instead use Qt:QueuedConnection . 如果在其他地方进行操作,则需要确保不使用Qt::AutoConnection ,而要使用Qt:QueuedConnection

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

Certain elements are only accessible from the "GUI" thread or the main thread of the program. 某些元素只能从“ GUI”线程或程序的主线程访问。 This is the thread that has QApplication::exec(); 这是具有QApplication::exec();的线程QApplication::exec(); ran on. 继续 It has an event loop that propagates messages around. 它具有一个事件循环,可以传播消息。

Look at the Application output for runtime errors that Qt will tell you about. 查看应用程序输出中Qt会告诉您的运行时错误。

When crossing thread boundaries, be sure to use signals and slots. 跨越线程边界时,请确保使用信号和插槽。

And if you are accessing a member of your thread class from outside that thread, be sure to use thread synchronization, practices, such as prefacing all access to these members with QMutexLocker locker(m_mutex); 而且,如果您要从该线程外部访问线程类的成员,请确保使用线程同步的做法,例如,使用QMutexLocker locker(m_mutex);前缀对这些成员的所有访问QMutexLocker locker(m_mutex); .

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

And as implied by the title "GUI thread", it is the only thread that is allowed to do certain things such as drawing QPixmap s and accessing certain parts of QWidget s. 正如标题“ GUI线程”所暗示的那样,它是唯一允许做某些事情的线程,例如绘制QPixmap和访问QWidget的某些部分。

Hope that helps. 希望能有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM