2015-04-03 3630 views
1

我想創建一個處理這個特定類的所有事件的Scanner類的線程,從而釋放GUI線程。我的GUI上有一個退出按鈕,它只是簡單地調用qApp-> quit()來退出應用程序,但我不知道如何處理我的Scanner類中的線程。在退出應用程序時,我在調試日誌中看到以下錯誤。退出應用程序安全退出Qt線程

QThread::wait: Thread tried to wait on itself 
QThread::wait: Thread tried to wait on itself 
QThread: Destroyed while thread is still running 

在Scanner.cpp(略其他功能)

Scanner::Scanner() : 
{ 
    this->moveToThread(&m_thread); 

    connect(&m_thread, &QThread::finished, this, &QObject::deleteLater); 
    connect(this, SIGNAL(StartEnroll()), this, SLOT(StartEnrollment())); 

    m_thread.start(); 
} 

Scanner::~Scanner() 
{ 
    m_thread.quit(); // Not sure if this is the correct 
    m_thread.wait(); 
} 

在主Window.cpp(略其他功能)

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    ui->setupUi(this); 
    connect(ui->ExitButton, SIGNAL(released()), this, SLOT(Quit())); 
    connect(&m_scanner, SIGNAL(FinishedEnroll(bool)), this, SLOT(EnrollDone(bool))); 
} 

void MainWindow::Quit() 
{ 
    close(); 
    qApp->quit(); 
} 

關於如何退出安全地退出該應用程序的任何指針在多線程應用程序中。

回答

2

您需要讓Scanner類知道應用程序正在退出。

以下行添加到的構造MainWindow

connect(qApp, SIGNAL(aboutToQuit()), &m_scanner, SLOT(deleteLater())); 

UPDATE:

connect(&m_thread, &QThread::finished, this, &QObject::deleteLater); 

不應該的Scanner

m_thread.quit(); 
m_thread.wait(); 
構造

不應該在Scanner

事實上析構函數,m_thread不應該以任何方式Scanner一部分。 QThread類不表示一個線程,它是一個線程管理器,應該從它創建的線程擁有和控制它。

在Qt中有很多使用線程的方法,很多沒有很好的記錄。如果你想使用使用線程的

workerObject->moveToThread(&thread); 
thread.start(); 

方式,那麼m_threadMainWindow類的成員,這些函數調用應該在它的構造函數中進行。

+0

這沒有奏效。我仍然得到:QThread :: wait:線程試圖自己等待 QThread:在線程仍在運行時被銷燬 – GMahan 2015-04-03 14:00:03

+0

Scanner類不應該試圖退出線程或等待線程。工作線程應該由GUI線程擁有和控制。 – RobbieE 2015-04-03 14:03:05

+0

謝謝,根據您的回覆發佈我的更正解決方案。 – GMahan 2015-04-03 14:47:29

0

首先,您應該將QThread移出掃描儀類。 A QThread管理一個線程,因此您不能調用與該線程本身內的線程管理相關的函數。這就是你得到關於等待自己線程的消息的原因。

你還是有這樣的事情:

m_scanner.moveToThread(&m_thread);//make the thread a member of your window 
m_thread.start(); 

然後,在你quit功能,做你想要的,無論是在線程等待(更好),或在退出之前結束它(糟糕的),或權衡,如:

void MainWindow::Quit() 
{ 
    close(); 
    //Wait maximum 1 second 
    if(!m_thread.wait(1000) { 
     m_thread.terminate(); 
    } 
    qApp->quit(); 
} 
+0

QObject不能在不同的線程中擁有子項。如果您將Scanner創建爲MainWindow的子項,然後將Scanner移動到其他線程,它將失去它的親子關係。 – RobbieE 2015-04-03 14:25:56

+0

哎呀,對,忘記了。 – JBL 2015-04-03 14:27:23

0

感謝您澄清和解決上面發佈的解決方案。以下是我之前發佈的內容。

ScannerThread.h

#include <QThread> 

class ScannerThread : public QThread 
{ 

public: 
    ScannerThread(); 
    ~ScannerThread(); 
}; 

ScannerThread.cpp

#include "scannerthread.h" 

ScannerThread::ScannerThread() 
{ 
    connect(this, &QThread::finished, this, &QObject::deleteLater); 
} 

ScannerThread::~ScannerThread() 
{ 
    quit(); 
    wait(); 

} 

在MainWindow.h

#include <QMainWindow> 

namespace Ui { 
class MainWindow; 
} 

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 

private slots: 
    void Quit(); 

private: 
    Ui::MainWindow *ui; 
    Scanner m_scanner; 
    ScannerThread m_scannerThread; 
}; 

在MainWindow.cpp(省略其他功能)

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    ui->setupUi(this); 

    m_scanner.moveToThread(&m_scannerThread); 
    m_scannerThread.start(); 

    connect(ui->ExitButton, SIGNAL(released()), this, SLOT(Quit())); 
    connect(qApp, SIGNAL(aboutToQuit()), &m_scanner, SLOT(deleteLater())); 

} 

void MainWindow::Quit() 
{ 
    close(); 
    qApp->quit(); 
} 

這似乎對我很好。如果您發現任何錯誤,請糾正,並感謝您的幫助。