2009-12-29 71 views
0

我正在將應用程序從QT3移植到QT4,並在線程更新QProgressDialog時繼續遇到問題。原代碼粗略設計,像這樣:將線程從QT3移植到QT4

class ScanProcess : QObject{ 
Q_OBJECT 
public: 
    QProgressDialog* progress; 
private: 
    ScanProcessThread* thread; 
}; 

class ScanProcessThread : QThread { 
Q_OBJECT 
public: 
    void run(); 
}; 

這是運行qt3to4,使從QT移植指南進行適當的更改後。

在最初的設計中,ScanProcessThread內:

void ScanProcessThread::run(){ 
//... 
ProgressInfo *prog = new ProgressInfo(); //then fill it in 
QCustomEvent* progEvent = new QCustomEvent(QEvent::User+1, (void*)prog); 
QCoreApplication::postEvent(parent, progEvent);//Parent is pointer to the ScanProcess 
//... 
} 

void ScanProcess::customEvent(QCustomEvent *e){ 
    if(e->type() == QEvent::User+1){ 
    //update QProgressDialog 
    progres->setValue(prog.index);//Value from the ProgressInfo passed above 
    //This line crashes deep in ntdll, but I have traced it to the QProgressDialog::repaint() 
    } 
} 

struct ProgressInfo {int count; int index; QString text;}; 

所以,這是最重要的代碼。對QProgressDialog :: Repaint的調用似乎總是在ntdll深處崩潰。我嘗試了兩種方法: 1)使用QCoreApplication :: postEvent() 2)傳遞QProgressDialog *並讓ScanProcessThread直接更新它。在每種情況下,都是失敗的QProgressDialog :: repaint()。有任何想法嗎?

(qt4.4中,Windows XP SP3時,Visual Studio 2008 /)

+0

只是一個說明,但我會讓我自己的自定義事件類來傳達進度信息,而不是鑄造成無效並返回。如果要發佈的對象不刪除指向的代碼,則發佈潛在的內存泄漏。此外,沒有任何東西可以釋放內存,如果該類發佈在處理事件之前消失,或者如果派生類覆蓋它並忘記這麼做,或者... – 2009-12-29 19:15:47

+0

@cjhuitt我會做很多不同的事情,如果我有自己編寫應用程序:)也就是說,這段代碼確實在自定義事件中清除了自己的指針(我忘了添加該行)。 – 2009-12-29 19:24:35

回答

0

由於只有主線程可以訪問GUI,你必須確保你處理日常ScanProcess::customEvent()在主線程。通常最簡單的方法是確保任何線程發出或處理信號都是own event loop

+0

我同意,崩潰使我認爲ScanProcess類不是在主線程中實例化的,而是在其他一些線程中實例化的。 – 2009-12-29 19:13:05

+0

爲什麼QT需要在主線程中進行GUI更新? – 2009-12-29 19:17:10

+0

@David Souther:GUI例程不是線程安全的。這是很難做到的,因爲在大多數操作系統中,GUI調用都有很多隱藏的本地狀態,而不是使用更細粒度的「每進程」索引,從而使得整個GUI API非線程安全 – Javier 2009-12-29 19:20:59