2017-01-03 50 views
0

假設在單線程應用中,我已創建了一個服務器和連接與像以下新的連接到達信號的槽,單線程應用QT時隙執行哪個線程

connect(mTcpServer, SIGNAL(newConnection()), this, SLOT(newClientConnected())); 

和這條線我進入後一個巨大的循環,我做了一些計算。因此,我的單線程是主線程正在循環中忙碌,現在有新的連接到達。

所以我的問題是,

1) In which thread the new slot will be executed? I ask this because 
main thread is already executing some code in a loop. 

2) In which thread the event loop is maintained? Because certainly my single 
thread is executing some code in a loop and is not maintaining the event loop. 

我在QT :(

+0

我不太明白這個問題:你說你有一個單線程應用程序。如在:只有一個線程。詢問插槽執行的線程是奇怪的:只有一個線程,您已經知道插槽將執行的線程! –

+0

@ KubaOber,我想不管事件循環總是在處理中。這就是爲什麼我很好奇,如果主線程不可用於處理那麼誰是它。 – Tahlil

+0

您需要提出一個更基本的問題:您爲什麼認爲信號和時隙與事件循環有什麼關係?在你的情況下,信號插槽連接**完全像**使用函數指針。插槽在信號的主體內被調用。當信號返回時(這只是一種方法,畢竟),插槽已被調用。沒有任何事件循環出現。事件循環用於提供跨線程/排隊插槽調用,但是你沒有這樣做。 –

回答

2

主線程。

既然你正在運行單線程應用程序,一切都會有處理(新手除了一些基本級別的IO)

您的插槽將始終在調用線程中執行,除非您創建一個Qt::QueuedConnection來運行sl在擁有該插槽的對象所屬的線程中。只要您運行多個線程,這一點就變得很重要。

每個標準QThread都有自己的事件隊列。既然你有一個單線程應用程序,你的事件隊列也將在主線程中運行。

在您的長時間運行循環期間結束時,不會有事件處理,也不會處理新的連接。

解決方案:使您的長時間運行計算在不同的線程中運行,以繼續處理新的連接和事件。你在這裏有不同的選擇。

  1. 在大多數的討論,但仍適用於沒有處理信號長時間運行的操作有點失寵/他們的計算過程中的事件是繼承QThread和重新實現run()功能。

  2. 將您的計算轉移到函數中,並使用QtConcurrent::run()運行它,該函數將自動使用線程。

  3. 創建QRunnable的子類並使用全局線程池。

所有的選項都是有效的,但在實現上稍有不同。有關更多詳細信息,請參閱文檔:http://doc.qt.io/qt-5/thread-basics.html

+0

非常感謝您的回答。如果我理解正確,如果一個線程空閒,那麼它的事件循環將在工作?在我的場景中,事件循環將不會執行任何操作,即使有新的連接也不會執行該插槽。 – Tahlil

+0

由於您的循環阻塞了線程,因此您將沒有事件處理。所以是的,你不會到達事件循環。您的連接處理由調用您的插槽的事件循環完成。一旦你從插槽返回,事件處理將繼續。 –

0

在哪個線程中維護事件循環?因爲當然我的單個線程正在循環中執行一些代碼,並且不維護事件循環。

每個線程都可以有一個事件循環。如果你的代碼沒有將控制權返回到它運行的線程中的事件循環中,那麼你將不會處理任何事件,並且正在設置自己的失敗。所以不要這樣做。轉換你的代碼如下:

// before 
forever { 
    code(); 
} 

// after 
void timerEvent(QTimerEvent *ev) { 
    if (ev->timerId() == m_timer.timerId()) 
    code(); 
} 

void start() { 
    m_timer.start(0, this); 
} 

QBasicTimer m_timer; // class member