問題描述
我是 Qt 新手,但需要解決一個難題.
I'm new to Qt, but need to solve a difficult problem.
我創建了一個非常簡單的 GUI,我需要將它添加到現有的 C++ 應用程序中.問題是,我只編寫了一個模塊,該模塊插入到一個更大的架構中,這限制了我對主線程的訪問.
I've created a VERY simple GUI that I need to add to an existing C++ application. The problem is, I'm writing just one module that plugs into a larger architecture which restricts my access to the main thread.
我的代碼必須位于以下四個函數中:一個 Init() 函數,它在主線程中運行.以及在工作線程中運行的 WorkerStart()、WorkerStep() 和 WorkerStop() 函數.
My code must reside inside the four following functions: an Init() function, which runs in the main thread. and WorkerStart(), WorkerStep(), and WorkerStop() functions that run in a worker thread.
我在 Init() 函數中編寫了 QApplication 和 GUI 對象.但當然,在該函數的末尾調用 app.exec() 會阻止整個其余代碼.不可行.
I coded my QApplication and GUI objects in the Init() function. But of course, calling app.exec() at the end of that function blocks the entire rest of the code. Not workable.
我所讀到的一切都表明 Qt gui 對象只能在主線程中運行.
Everything I'm reading says that Qt gui objects can only run in the main thread.
所以我的問題是,如何在 init() 函數(主線程)中設置我的 gui 并允許它從那時起僅使用工作線程運行?
So my question is, how can I set up my gui in the init() function (main thread) and allow it to run by only using the worker thread from then on?
我發現了這個:非主線程中的 QApplication
這些解決方案給了我一些不同的行為.方向正確,但不穩定或功能不全.但是我不明白如果qt gui只能在主線程中運行,為什么這些都是解決方案,而這些解決方案將它們放在其他線程中.所以這就是發送關于什么可以和不能在其他線程中運行的混合消息,這變得非常混亂.
and those solutions gave me some different behavior. In the right direction, but not stable or fully functional. But I dont understand why those are solutions at all if qt gui's can only run in main thread, and these solutions put them in other threads. So thats sending mixed messages on what can and can not run in other threads, and it becomes very confusing.
向現有 C++ 程序添加 gui 而不將其鎖定在 exec() 函數中似乎是一種相當普遍的情況,所以我覺得我遺漏了一些明顯的東西.有人可以幫助我解決這個問題嗎?
It seems that adding a gui to an existing C++ program without locking it up in the exec() func should be a fairly common situation so I feel like I'm missing something obvious. Can someone help with how I can solve this?
非常感謝.菲爾
推薦答案
大多數時候,主線程"==GUI 線程",所以人們交替使用這些術語——即使是官方文檔也是如此.我同意這很令人困惑,因為它們不必相同.^ 實際規則是這樣的:
Most of the time, "main thread" == "GUI thread", so people use those terms interchangeably -- even the official documentation does that. I agree that it's confusing though, because they don't have to be the same.^ The actual rule is this:
GUI 類只能從實例化 QApplication
/QGuiApplication
GUI classes must only be accessed from the thread which instantiates
QApplication
/QGuiApplication
使用像您這樣的插件,您需要執行以下操作:
With a plugin like yours, here is what you need to do:
- 創建一個新的
std::thread
(不是QThread
) - 在該線程中運行
init
函數.讓它實例化你的QApplication
/QGuiApplication
并啟動事件循環 - 確保所有 GUI 對象只能從該線程訪問.
- Create a new
std::thread
(NOT aQThread
) - Run an
init
function in that thread. Let it instantiate yourQApplication
/QGuiApplication
and start the event loop - Ensure that all your GUI objects are accessed from that thread only.
瞧,您現在擁有一個不是主線程的 GUI 線程.
Voila, you now have a GUI thread that is not your main thread.
^注意:在 Mac OS X 上情況不同.由于 Cocoa 框架的限制,主線程必須是 GUI 線程.我上面概述的步驟適用于 Windows/Linux,但不適用于 Mac.對于 Mac,您需要將代碼注入主線程——請參閱下面的 Kuba Ober 的評論.
^Note: It is a different story on Mac OS X. Due to restrictions in the Cocoa framework, the main thread MUST be the GUI thread. The steps I outlined above will work on Windows/Linux but not on Mac. For Mac, you need to inject your code into the main thread -- see Kuba Ober's comments below.
這篇關于如何避免 Qt app.exec() 阻塞主線程的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!