[英]Qt Creator crashes when using multiple threads
我正在編寫Qt(5.3)程序,其中包含操縱桿測試UI,但是我需要一個單獨的線程用於無限while循環,以通過SDL查找操縱桿軸/按鈕值更改。 代碼的這一部分工作正常,因為我可以使用線程qDebug()消息,並且似乎可以正常工作。 但是從主窗口中,當我嘗試打開測試操縱桿UI時,程序崩潰了。 我已經在沒有JoystickThread線程的情況下使測試操縱桿UI運行分離,並且似乎可以正常運行。
錯誤消息雖然不一致-有時,我只是得到
該程序意外完成。 / 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();這很常見。 不是在主函數中運行,但是即使在主函數上運行,它也因相同的錯誤而崩潰。
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();
非常感謝你! 如果您需要更多信息,請告訴我。
QThread
有些棘手,並且有一些麻煩。
您應該在運行功能的頂部構造並連接適當的項目。
如果在其他地方進行操作,則需要確保不使用Qt::AutoConnection
,而要使用Qt:QueuedConnection
。
http://qt-project.org/doc/qt-5/qt.html#ConnectionType-枚舉
某些元素只能從“ GUI”線程或程序的主線程訪問。 這是具有QApplication::exec();
的線程QApplication::exec();
繼續 它具有一個事件循環,可以傳播消息。
查看應用程序輸出中Qt會告訴您的運行時錯誤。
跨越線程邊界時,請確保使用信號和插槽。
而且,如果您要從該線程外部訪問線程類的成員,請確保使用線程同步的做法,例如,使用QMutexLocker locker(m_mutex);
前綴對這些成員的所有訪問QMutexLocker locker(m_mutex);
。
http://qt-project.org/doc/qt-5/threads.html
正如標題“ GUI線程”所暗示的那樣,它是唯一允許做某些事情的線程,例如繪制QPixmap
和訪問QWidget
的某些部分。
希望能有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.