問題:
在Qt 中,您希望在任何具有事件循環的執行緒中執行lambda 或仿函數,類似於Objective-C 中的GCD 調度佇列。
解決方案:
解決方案的核心是傳遞一個事件,將函子包裝到駐留在所需線程中的消費者物件。此操作稱為 元呼叫發布,可以透過多種方式實現。
Qt 5.10 以上 TL;DR:
您可以呼叫 QObject 或 QThread上的方法直接:
// Invoke on the main thread QMetaObject::invokeMethod(qApp, []{ ... }); // Invoke on an object's thread QMetaObject::invokeMethod(obj, []{ ... }); // Invoke on a particular thread QMetaObject::invokeMethod( QAbstractEventDispatcher::instance(thread), []{ ... });
TL;函子的DR:
提供了幾個模板函數來將函子包裝在適當的事件物件中,使元呼叫發布變得方便。
// Post to the main thread sync void execInMainThread_sync(std::function<void(void)> func) { if(qApp->thread() == QThread::currentThread()) func(); else { ((App*) qApp)->invokeGenericExec(func, Qt::BlockingQueuedConnection); } } // Post to the main thread async void execInMainThread_async(std::function<void(void)> func) { ((App*) qApp)->invokeGenericExec(func, Qt::QueuedConnection); }
TL;DR方法/槽:
對於方法或槽,定義一個巨集來處理元呼叫發布。
#define POST_METHOD(obj, method) \ QObject src; \ QObject::connect(&src, &QObject::destroyed, obj, method, \ Qt::QueuedConnection);
通用程式碼:
提供的程式碼包括常見的輔助函數和宏,它們抽象化了元呼叫發布實作以在不同的環境中使用
範例:
void test1() { QThread t; QObject o; o.moveToThread(&t); // Execute in given object's thread postToObject([&]{ o.setObjectName("hello"); }, &o); // or postToObject(std::bind(&QObject::setObjectName, &o, "hello"), &o); // Execute in given thread postToThread([]{ qDebug() << "hello from worker thread"; }); // Execute in the main thread postToThread([]{ qDebug() << "hello from main thread"; }); }
附加說明:
如果您的目標線程沒有事件循環例如工作線程,您可能需要一種機制來啟動線程內的事件循環。例如,如果使用單次計時器進行元呼叫發布,則可以使用 QThread::exec() 啟動事件循環。
以上是如何在特定的 Qt 線程中執行 Functor 或 Lambda,類似於 GCD?的詳細內容。更多資訊請關注PHP中文網其他相關文章!