2010-04-01 119 views
2

我正在使用Qt並希望編寫一個類來執行一些類似於FTP/HTTP的網絡類型操作。該類需要依次連接到大量機器,但我需要應用程序UI在此過程中保持(相對)響應,因此用戶可以取消操作,退出應用程序等。我的第一個想法是使用一個獨立的網絡線程,但內置的Qt FTP/HTTP(和其他)類顯然避免使用線程,而是依賴於信號和插槽。所以,我希望做同樣的事情,並希望我可以做這樣的事情:使用Qt信號/插槽而不是工作線程

class Foo : public QObject 
{ 
    Q_OBJECT 
public: 
    void start(); 

signals: 
    void next(); 

private slots: 
    void nextJob(); 
}; 

void Foo::start() 
{ 
    ... 
    connect(this, SIGNAL(next()), this, SLOT(nextJob())); 
    emit next(); 
} 

void Foo::nextJob() 
{ 
    // Process next 'chunk' 

    if (workLeftToDo) 
    { 
    emit next(); 
    } 
} 


void Bar::StartOperation() 
{ 
    Foo* foo = new Foo; 
    foo->start(); 
} 

然而,這並不工作,UI凍結,直到所有操作完成。我希望發出的信號不會立即調用插槽,但會以某種方式被Qt排隊,允許主UI仍然可以運行。

那麼,爲了做到這一點,我需要做些什麼? Qt如何通過衆多內置類來實現這一點,這些內置類似乎在單個線程上執行冗長的任務?

+0

如果您想要確保插槽在發出信號時排隊,您可以將其指定爲連接功能的最終參數。 – 2010-04-01 17:37:36

回答

3

如果您在UI線程中執行一項長工作,UI將凍結。避免這種情況的一種方法是在一段時間內撥打電話QCoreApplication::processEvents()

但是你應該非常小心,但是在你決定做這件事之前,要明白它的作用。調用這個函數意味着一個GUI事件可以在操作過程中觸發。如果這個事件又可以創造更多的工作,那麼你可以在舊工作中間開始一項新工作。

我不會那麼快地解僱工作者線程的方法。它具有將工作與GUI完全分開的優勢,因此您可以確定開始的工作即將完成。
您還應該考慮Windows特別有時會在GUI循環中引入不重要的延遲。如果主機有些繁忙或處於內存抖動狀態,則會發現GUI事件可能需要長達幾秒的時間才能完成並將控制權返回給您的處理。

+0

我只是查找QThread,它是a)易於實現,b)像任何其他QObject一樣支持信號/插槽。感謝您的建議。 – Rob 2010-04-01 09:54:29

2

使用的QThread有這樣的run方法:

void run(){ exec(); } 

這將提供另一執行循環,在那裏你可以做你的「努力工作」,而不實際上可以凍結UI。

注:確保實際上在你的QThread派生Thread類的構造函數的年底加入

moveToThread(this); 

使用線程的執行循環(DOC沒有說太多關於它)

+0

http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/ – alisami 2011-04-22 17:19:06

+0

正如您在離開我的評論後發佈artice的日期所見。到那個時候,關於如何做到這一點的唯一參考是Qt文檔,它說明了這一點以及Qt示例。 – drahnr 2011-04-23 06:18:34