2014-05-22 5 views
1

모든 대화를 저장하기 위해 SQLite 데이터베이스를 사용하는 작은 대화 응용 프로그램이 있습니다. 나는 앱이 무작위로 얼어 붙는 것을 알아 차렸다. 그런 다음 앱을 다시 작동 시키려면 최소화하고 최대화해야한다. 문제는 GUI가 멈추는 원인이되는 SQLite select/inserts 일 수 있다고 생각했습니다. 모든 SQLite 메서드를 별도의 스레드로 옮기려고했습니다.별도의 스레드에서 실행중인 Im 임에도 불구하고 QT GUI가 작동하지 않습니다.

이렇게하면 앱이 계속 정지됩니다.

가치가있을 수도 있습니다 어떤 것들은 알고 :

  1. 내가 내 MainWindow에서 직접 QTcpSocket를 사용하지만 별도의 스레드에서 QTcpSocket를 실행에 아무 소용이없는 것 같다을?

  2. 나는 새 스레드에 SQLite는 방법을 분리 한 내 채팅 메시지를 표시하는 3 WebViews를 사용

  3. (아래 구현을 참조), 전체 응용 프로그램의 GUI는이 WebViews

빌드입니다

아래 코드는 실제로 별도의 스레드에서 실행됩니까? GUI가 여전히 고정되어 있습니다.

내 헤더 파일 :

class dbThread : public QObject 
{ 
    Q_OBJECT 

public: 
    dbThread(QObject* parent); 

public slots: 
    bool openDB(QString agentID); 

signals: 
    void clearPreviousHistory(); 

private: 
    QSqlDatabase db; 
    QHash<QString, QString> countries; 
}; 

내 CPP 파일 :

dbtrad->getHistory(channelId); 

편집

: 내 MainWindow에서 dbThread 메소드를 호출하는 방법을

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
QThread* thread = new QThread(this); 
dbtrad = new dbThread(this); 
dbtrad->moveToThread(thread); 

dbtrad->openDB(userID); 

connect(dbtrad, SIGNAL(clearPreviousHistory()), this, SLOT(clearHistoryV())); 
thread->start(); 

} 



dbThread::dbThread(QObject * parent): QObject(parent) { 
} 

bool dbThread::openDB(QString agentID) { 

    qDebug() << "OPEN DB FROM THREAD "; 

    // Find QSLite driver 
    db = QSqlDatabase::addDatabase("QSQLITE"); 

    // ...... 
} 

이것은

새로운 코드 :

// Start database thread 
QThread* thread = new QThread(this); 
dbtrad = new dbThread(this); 
dbtrad->moveToThread(thread); 

connect(this, SIGNAL(requestOpenDB(QString)), dbtrad, SLOT(openDB(QString))); 
thread->start(); 

emit requestOpenDB(userID); 
+0

여기서 dbthread 함수를 호출하는 코드를 보여줍니다. 또한 메인 스레드에서 호출합니까? 'moveToThread'가하는 일을 오해 할 수도 있습니다. –

+0

편집을 참조하십시오. 메인 스레드에서 db 메소드를 호출하는 방법을 게시했습니다. – Alosyius

+0

[QThread :: currentThreadId() ** 경고 : **이 함수에서 반환하는 핸들은 내부 용으로 사용되었으므로 응용 프로그램 코드. ** 경고 : ** Windows에서 반환 값은 현재 스레드의 의사 핸들입니다.] (http://qt-project.org/doc/qt-4.8/qthread.html#currentThreadId) – UmNyobe

답변

2

dbtrad->openDB(userID);가 (왜 그것을해야합니까?) 어떤 정상적인 기능처럼 실행됩니다의 GUI 스레드에서 .

moveToThread

당신에게 는 신호를 별도의 스레드에서를 사용하여 호출 슬롯을 실행할 수 있습니다.

당신은 당신이 사용하여 실행을 트리거 할 수 있습니다 스레드에 openDB을 실행하려면

connect (thread, SIGNAL(started()), dbtrad, SLOT(openDBWithUIDAlreadySet())) 

또는 당신은 기존 또는 추가 신호를 사용할 필요가

connect (this, SIGNAL(requestOpenDB(int)), dbtrad, SLOT(openDB(int))) 

. Qthread::start()started() 신호를 내 보냅니다.또한

MainWindow{ 

signals: 
    void requestOpenDB(int); 
    void queryHistory(int channelid); 
} 

정의 수동 dbThread 개체로부터 응답도 슬롯에 접속되는 신호를 이용하여 부여 할 필요

emit requestOpenDB(userID); //for openDB 
emit queryHistory(channelId); // for getHistory 

를 사용하여 신호를 방출 할 수있다. 통보처럼.

+0

Ahhh I see!연결을 사용하여 모든 db 호출을 업데이트하고 작동하는지 확인하십시오. – Alosyius

+0

대신 연결로이 호출을 작성하는 방법은 무엇입니까? – Alosyius

+0

MainWindow 내부와 스레드 내부에서 모두'qDebug() << this-> thread() -> currentThreadId();'를 출력하려고했는데 같은 결과를 얻었습니다 :'0x7fff7300f180' – Alosyius

0
  1. QTcpSocket 정말로 분리 된 스레드 일 필요는 없습니다.

  2. 만큼 모든 데이터베이스 액세스 데이터베이스가 그것도

  3. 이제 재미있는 부분에는 문제가 없습니다 생성 된 스레드에서 수행 될 때

  4. : 난 당신이 메인 스레드에서 데이터베이스를 만들 생각 ...

0

dbtrad->openDB(userId)를 호출하여 예 당신이 어떻게 기대하고 무엇을하지 않습니다 moveToThread() 그래서 QT. 주 스레드에서 호출하는 함수는 주 스레드에서만 실행됩니다. 해당 데이터베이스 액세스로 인해 GUI가 정지되었습니다.

moveToThread은 별도의 스레드에서 "이벤트 처리"만 이동합니다. 즉, Qt::QueuedConnection을 사용하여 연결된 dbThread 슬롯은 새 스레드에서 실행됩니다.

다음과 같은 방법으로 메인 ui 스레드에서만 getHistory() 메서드를 실행합니다. 메인 스레드에서 신호를 만들고 getHistory() 슬롯을 dbThread 슬롯으로 만들어야합니다. 그런 다음 둘 다 연결하십시오.

0

설명서 및 로그를 읽는 것이 필수적입니다 !!! 로그에서
당신은 객체가 부모가있는 경우 당신이 "T 이동이 스레드 CAN 경고가 또한 documentation clearly says that :..

이 객체와 그 아이들을위한 스레드 선호도를 변경하는 객체가 을 이동할 수 없습니다 . 그 부모가 있으면 이벤트 처리 targetThread에 계속


적절한 방법은 그것을 해결하기 위해 :.

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    thread = new QThread(this); 
    dbtrad = new dbThread(); // NO PARENT 
    dbtrad->moveToThread(thread); 

    // run object method in thread assigned to this object: 
    QMetaObject::invokeMethod(dbtrad, "openDB", Qt::QueuedConnection, Q_ARG(QString, userID)); 

    connect(dbtrad, SIGNAL(clearPreviousHistory()), this, SLOT(clearHistoryV())); 
    thread->start(); 
} 

MainWindow::~MainWindow() 
{ 
    dbtrad->deleteLater(); 
    thread->quit(); 
    thread->wait(5000); // wait max 5 seconds to terminate thread 
} 
+0

로 게시물을 업데이트했습니다. 어떻게 수정 될 수 있습니까? 잘 작동하는지 확인하려면 무엇을해야할지 모르겠 음 – Alosyius

+0

부모를 설정하지 마십시오. 편집을 참조하십시오. 'dbtrad-> openDB'를 주 윈도우의 신호에 연결하고'userID'를이 방법으로 전달하거나 메타 데이터 호출을 사용하여 수행하는 것처럼해야합니다. –

관련 문제