2014-02-28 70 views
2

我有一個類,audio_engine_interface,並在main.cpp中,我將它添加到QML的東西。QThread和QML鎖定

viewer.rootContext()->setContextProperty("engine", engine); 

在audio_engine_interface,我有一個audio_engine類,它是計算密集型的,它需要在自己的線程中運行。但是,當我這樣做時,整個QML線程鎖定了,這意味着我不能暫停(非常重要)。我錯過了什麼嗎?

編輯: 此線程不會搞亂任何東西或從其他地方訪問對象。但是,它有一個暫停功能,需要在某個時候調用。對於它的價值,引擎正在進行音高轉換。

+0

是的,這裏有一個QML特定的機制。否則,GUI線程是GUI線程,並且是唯一可以渲染的線程。 http://qt-project.org/doc/qt-5/qml-qtquick-workerscript.html – user1095108

+0

我使用的是C++,而不是Javascript。 – Jacob

+1

是的,但你可以從javascript調用C++,反之亦然。所以這與你所使用的幾乎無關。 – user1095108

回答

1

這是一個問題: -

Qthread thread; 

創建這樣一個QThread的對象被創建它在堆棧上。當函數結束時,對象將超出範圍並刪除QThread對象。

你需要動態地分配在堆上的對象: -

QThread* thread = new QThread; 

然後記得刪除線,或將其設置爲刪除自己: -

//Qt 5 connect syntax 
connect(thread, &QThread::finished, thread, &QThread::deleteLater); 

你也應該知道線程關聯性(運行對象的線程)。我建議閱讀this article關於如何正確使用QThread。

+0

我正在做這個方法 - 雖然不太清楚deleteLater,我想重用這個線程,或者至少是引擎。並且它不會導致QML在播放時凍結。但是,暫停時,它確實如此。任何指針爲什麼這可能是? – Jacob

+0

忽略這一點。有一個揮之不去的audio_decoder進程導致它掛斷。謝謝您的幫助! – Jacob

+1

沒問題。很高興你得到它排序; O) – TheDarkKnight

1

你有這麼多問題。

  1. 當你移動到線程的對象不能有父
  2. 你的線程對象是本地變量,因此它會一天時立即udio_engine_interface::play()末執行
  3. 您直接engine->play();方法調用你,這意味着它將在當前線程中執行。

moveToThread意味着由信號invked槽使用缺省參數第五(Qt::AutoConnection)將在給定線程的事件循環排隊連接。

解決它最簡單的方法是使用QtConcurrent

void audio_engine_interface::play() 
{ 
    QtConcurrent::run(engine, &EngineClass::play); 
} 

根據你的發動機不會你應該讓線程安全的(使用互斥鎖的等等),沒有細節就很難說,有什麼你應該這樣做。

+0

如果我這樣做,我可以調用引擎 - >暫停()? – Jacob

+0

@MarekR,你可能會對這個關於QtConcurrent和QFuture的主題感興趣:http://comments.gmane.org/gmane.comp.lib.qt.devel/7942 – TheDarkKnight

+0

我已經看到了,我仍然會使用'QtConcurrent :: run'(其他'QtConcurrent'具有較低的實際價值)。 –