問題:
Qt では、次のようなイベント ループを持つスレッドでラムダまたはファンクターを実行したいとします。 Objective-C の GCD のディスパッチ キュー。
解決策:
この解決策は、ファンクターをラップするイベントを目的のスレッドに存在するコンシューマー オブジェクトに配信することを中心としています。この操作は メタコール ポスティング と呼ばれ、いくつかの方法で実装できます。
Qt 5.10 以降 TL;DR:
QObjects または QThreads でメソッドを呼び出すことができます直接:
// 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() を使用してイベント ループを開始できます。
以上がGCD と同様に、特定の Qt スレッドでファンクターまたはラムダを実行するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。