2014-10-04 698 views
0

我正在写一个Qt(5.3)程序,其中包含一个游戏杆测试UI,但我需要一个单独的线程用于无限while循环,以通过SDL查找操纵杆轴/按钮值更改。代码的那部分工作正常,因为我可以有线程qDebug()消息,它似乎工作。但是从主窗口中,当我尝试打开测试游戏杆UI时,程序崩溃。我的测试游戏杆用户界面在没有JoystickThread线程的情况下运行分离,并且它看起来很好。Qt Creator在使用多线程时崩溃

的错误信息不一致,但 - 有些时候,我只是得到

该方案已完成意外。 /家庭/ narendran/QtWorkspace /内建连接控制 - 桌面 - 调试/连接控制坠毁

这已经显示出了一次:

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

以及其他一些时间:

[xcb]处理队列中未知的序号 [xcb]很可能这是一个多线程客户端,并且XInitThreads尚未被称为 [xcb]正在中止,对此感到抱歉。 star:../../src/xcb_io.c:274:poll_for_event:声明`!xcb_xlib_threads_sequence_lost'失败。

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

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

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

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

回答

0

QThread s有点棘手,最初习惯,并有他们的陷阱份额。

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

如果你这样做了其他地方,你需要确保你不使用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线程”所暗示的,它是允许做某些事情,如绘画QPixmap S和访问的QWidget条某些部件的唯一线索。

希望有所帮助。

+0

出于好奇,这里有哪条评论,解决了你的问题? @NarendranMuraleedharan – phyatt 2014-10-06 04:03:08

+0

将线程静音以控制数据流入变量。 – 2014-10-10 08:45:36