2013-02-06 82 views
0

這是QThread的子類的run方法:Qt的線程和循環問題

void crono::Controller::run() { 

    //initialise timer 
    int *i = & this->model->seconds_elapsed; 

    for (*i = 0; *i < this->model->seconds_total; (*i)++) { 

    //calculate current seconds/minutes/hours elapsed starting from seconds_elapsed (*i) 
    this->model->tick(); 

    //should display in the form the time elapsed 
    this->vista->showTime(); 
    sleep(1000); 


    } 

    Beep(1000, 500); //beep when all is over 

} 

控制器更新模型值。

QT表單在開始時打開,我想在主應用程序線程中。

問題是,對debug * i = 0和seconds_total = X> 0的鄙視,循環只執行一次,在第一次調試停止後(它沒有結束),表單彈出但沒有任何發生。

我唯一能猜到的是控制器線程失去了優先級,從來沒有再次獲得CPU。

如何避免這種情況?

編輯 我使用QTimer,與倒黴嘗試。

我聲明更新爲公共時隙,然後這樣來實現:

void crono::Controller::update() { 

    this->modello->tick(); 
    this->vista->showTime(); 

    //eventually stop at some point (pointer to timer and timer->stop()? 
    //... 
    //Beep(1000, 500); 
} 

我插入QTimer在控制器(線程)對象,而不是循環週期:

void crono::Controller::run() { 

    //inizializzo timer 
    int *i = & this->modello->secondi_trascorsi; 

    QTimer *timer = new QTimer(this); 
    connect(timer, SIGNAL(timeout()),this, SLOT(update())); 
    timer->start(1000); 


} 

我不知道爲什麼,但update()方法永遠不會被調用,而不是被稱爲無限次數。爲什麼?

+0

不,我不認爲這可能是問題。調試或添加一些調試日誌記錄來檢查是否達到睡眠子句。也許其他方法之一導致無限循環? –

+0

「//應該以流逝的時間的形式顯示」 - 您確定沒有直接從線程訪問GUI,而是僅通過信號/插槽來訪問GUI? – borisbn

+2

我強烈建議保持QThread和實現彼此分離,即不要繼承QThread(閱讀Zaiborg的鏈接)。如果你真的重新實現'QThread :: run()',你需要在'run()'方法的末尾調用'exec()',否則任何事件(包括信號)都不會被線程處理。 –

回答

2

正如Tim Meyer在他的評論中指出的,您需要在QThread::run()實現的末尾調用QThread:exec(),這是爲了啓動線程的事件循環,這是Signal/Slot機制的工作所必需的。

但是,它好像是you're doing it wrong

+0

我做錯了,因爲博客文章暗示要繼承QThread/meh – alessiop86

+2

我想即使是Qt文檔也暗示了一段時間。 非常好的示例:http://qt-project.org/doc/qt-4.8/QThread.html#details –

1

我敢肯定,你的循環應該是這樣的:

//initialize timer 
int elapsed = this->model->seconds_elapsed; 

for (int i = 0; i < elapsed; i++) 

我認爲沒有必要使用指針。把事情簡單化。

如果這仍然不起作用,那麼你做的其他事情不對,而且你的代碼並不明顯。

此外線程信令不使用sleep完成。爲了線程信號的目的,您應該查看線程事件,如信號量或條件變量。

如果您想定期更新值,爲什麼不使用QTimer?

sleep只有很少的有效用途,我相信你正在解決一個不需要睡眠的問題。

+0

爲了在每個週期更新模型的狀態需要一個指針 – alessiop86

2

首先,QThread不應該由於幾乎任何原因而被繼承。

線程通常會像有描述來完成:http://qt-project.org/doc/qt-4.8/QThread.html#details

如果你只需要線程來算一段時間,一段時間後做的東西,也許你可以使用QTimer代替和QTimer::timeout()信號連接到您的插槽顯示已用時間。

4

一個常見的混淆是QThread運行在它自己的單獨線程中。不是這種情況;相反,QThread會在其控制的子線程中啓動事件循環。 QThread很容易被稱爲QThreadManager

總之,不要子集QThread,因爲您創建的功能駐留在主線程(而不是QThread處理的線程)。使用連接到started()信號的插槽創建一個QObject子類。然後使用moveToThread()並在QThread實例上調用run()

另外,您不能直接從子線程調用主線程函數。你需要一個排隊連接信號給主線程中的對象來顯示對話框。