2016-08-19 403 views
1

不發出信號在以下代碼中省略waitForFinished()使QProcess停止發出其信號。它有什麼問題?這是一個Qt錯誤? (5.7)。請注意,此代碼與QtConcurrent運行並行運行。但是,這不應該改變什麼,應該嗎? Afaik在其他線程發送信號很好,但它們會排隊。QProcess在不waitForFinished()

​​
+0

您是否已將所有此代碼放入傳遞給'QtConcurrent :: run'的lambda函數中? – Mike

回答

3

你沒有運行在該QProcess實例所在線程的事件循環。沒有事件循環的線程中的任何QObject都只是部分功能 - 定時器不會運行,排隊的調用將不會被髮送等。所以你不能這樣做。使用QObjectQtConcurrent::run需要注意。

至少,只要進程處於活動狀態,就應該有一個臨時事件循環 - 在這種情況下,應該按值保存QProcess,因爲事件循環退出後將不會執行deleteLater

QProcess process; 
... 
QEventLoop loop; 
connect(process, &QProcess::finished, &loop, &QEventLoop::quit); 
loop.exec(); 

否則,你需要保持更持久的線程的進程,並保持該線程處理(QThread不過是手柄!),因爲有一個事件循環,當它這樣做,可以處理它的線程。

// This can be run from a lambda that runs in an arbitrary thread 

auto thread = new QThread; 
auto process = new QProcess; 

... 

connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), 
    [this, process](int exitCode, QProcess::ExitStatus exitStatus){ 
    ... 
    process->deleteLater(); 
    process->thread()->quit(); 
}); 

process->start("VBoxManage", {"list", "vms"}); 
process->moveToThread(thread); 

// Move the thread **handle** to the main thread 
thread->moveToThread(qApp->thread()); 
connect(thread, &QThread::finished, thread, &QObject::deleteLater); 
thread->start(); 

唉,這是非常愚蠢的,因爲你正在創建臨時線程,這是昂貴和浪費。您應該有一個額外的工作線程,您可以負責所有低開銷工作,例如QProcess交互。該線程應該始終運行,並且您可以將所有QProcess和類似的對象實例從併發lambda等移動到它。

+0

有這樣的多個工作必須完成。我使用Concurrent,因爲這樣我可以輕鬆使用所有內核。但是,爲什麼它不起作用呢?它是lambda?我調用的對象在主線程中。將使lambda成員函數工作? – ManuelSchneid3r

+0

對不起,這聽起來很愚蠢,但不是來自已經運行事件循環的'QThreadPool'線程? (例如,爲了執行傳遞給'QThreadPool :: start'的函數) – Mike

+1

我已經說了爲什麼它不起作用:這是因爲像'QProcess'這樣的'QObject'是可用的,線程它運行時必須運行一個事件循環!它沒有任何**與lambda或類似的東西。你調用'run'的對象是不相關的:lambda運行在沒有事件循環的工作線程中。 –