2013-05-30 590 views
2

刪除的SerialPort導致此消息在調試版本:Qt的錯誤與QSerialPort在多線程代碼:QCoreApplication ::的SendEvent:「無法將事件發送到一個不同的線程擁有的對象

ASSERT失敗QCoreApplication ::的SendEvent:」不能將事件發送給不同線程擁有的對象。當前線程c0a528。接收器「」(QSerialPort「型」)螺紋c76850" ,文件內核\ qcoreapplication.cpp創建,線532

實際的錯誤是在〜QSerialReader觸發時關閉主窗口。下面的代碼。

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    runnerThread=new QThread(this);  
    /* - connect thread start signal to qrunnerthread's runLoop() 
     this starts the main job loop    
     - connect thread finished signal to mainwindows' deleteLater 
     to ensure proper deletion */ 
    qDataReader = new QDataReader(); 
    connect(runnerThread, SIGNAL(started()), qRunnerThread, SLOT(runLoop()));  
    connect(runnerThread, SIGNAL(finished()), this, SLOT(deleteLater())); 
    qDataReader->moveToThread(runnerThread); 
    runnerThread.start(); 
} 

MainWindow::~MainWindow() 
{ 
    runnerThread->exit(); 
} 

//slot that runs when thread is started 
void QDataReader::runLoop() { 
    /* this code runs in different thread than QDataReader */  
    //serialPort parent will be QThread (runnerThread) 
    serialReader=new QSerialReader(this);   

    while(doStuff) {  
     QString data=serialReader.readData(); 
     emit dataReceived(data);  
    } 
} 

QDataReader::~QDataReader() { 
    delete runner; 
} 

QSerialReader::QSerialReader(QObject* parent) { 
    //serialPort parent will be QSerialReader 
    serialPort = new QSerialPort(this); 
} 

QSerialReader::~QSerialReader() { 

    /* 
    deleting serialPort causes this message in debug builds: 

    ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread c0a528. Receiver '' (of type 'QSerialPort') was created in thread c76850", file kernel\qcoreapplication.cpp, line 532 
    */ 
    delete serialPort; 
} 

EDIT1:佩普的建議:

如果我QSerialReader更改爲QDataReader成員的問題消失,但與QSerialPort打開端口時,::打開這個錯誤出現。

的QObject:無法創建爲一位父母的孩子在不同的線程中。 (父爲QSerialPort(0xdf6930),父線程爲QThread(0xd8a528),當前線程爲QThread(0xdf6850) QObject:無法爲處於不同線程的父級創建子級 線程的QThread(0xd8a528),當前線程的QThread(0xdf6850)

QSerialPort ::打開(XX)被稱爲內部serialReader.readData();

所以還是......一些棘手的問題,我沒有有這樣的問題,當我在Java中,幾年前編碼。

stack trace when CSerialReader::openPort is called. this calls QSerialPort::open. Clearly this is run in other thread than main. 

0 CSerialReader::openPort serialreader.cpp 480 0xff7211  
1 CSerialReader::readData serialreader.cpp 209 0xff4e1d  
2 QDataReader::runLoop qdatareader.cpp 138 0xffa3fe  
3 QDataReader::qt_static_metacall moc_qdatareader.cpp 62 0x1040824 
4 QMetaObject::activate qobject.cpp 3539 0x669b0e14 
5 QThread::started moc_qthread.cpp 113 0x66a29979 
6 QThreadPrivate::start qthread_win.cpp 345 0x66816918 
7 _callthreadstartex threadex.c 314 0xf71a293 
8 _threadstartex threadex.c 297 0xf71a224 
9 BaseThreadInitThunk kernel32  0x74cd3677 
10 __RtlUserThreadStart ntdll32  0x76f9c002 
11 _RtlUserThreadStart ntdll32  0x76f9bfd5 

創建CSerialReader時的堆棧跟蹤(作爲成員變量)。這在主線程中被調用。

0 CSerialReader::CSerialReader Runner.cpp 48 0x9d3d14  
1 QDataReader::QDataReader qdatareader.cpp 10 0x9d8fa4  
2 MainWindow::MainWindow mainwindow.cpp 72 0x9c61eb  
3 main main.cpp 105 0x9c4adc  
4 WinMain qtmain_win.cpp 131 0xa273ba  
5 __tmainCRTStartup crtexe.c 547 0xa269e0  
6 WinMainCRTStartup crtexe.c 371 0xa2676f  
7 BaseThreadInitThunk kernel32  0x74cd3677 
8 __RtlUserThreadStart ntdll32  0x76f9c002 
9 _RtlUserThreadStart ntdll32  0x76f9bfd5 

回答

2
serialReader=new QSerialReader(this); 

不要這樣做。父母和孩子必須共同生活。在你的情況下,父母(QThread)生活在自己的線程中,孩子(QSerialReader)生活在你生成的線程中。你不能把它分配在棧上嗎?

+0

感謝您的回覆!我會稍後再嘗試。但runLoop()在runnerThread親和性中運行,對吧?所以'this'是一個指向runnerThread的指針。那裏沒問題我認爲 –

+0

peppe:我試過了,但現在又出現了另一個錯誤。檢查原始帖子。我添加了關於這個的信息。 –

+0

你可以在打印該警告的語句(在Qt內)上放置一個斷點,然後查看堆棧跟蹤? – peppe

相關問題