2017-01-27 13 views
1

私は非常に気まずいバグに遭遇しました - は、ブロックされたダイアログを表示して、triggerと呼ばれる私のサーバーを停止させました(例えば、閉鎖されました)。コードをクリアしてスロットを非同期で呼び出してください

回避策を見つけました。私はQt::QueuedConnectionを使用してQAction::triggerをスロットに信号void triggerWorkaround()を接続して、私はそれを発する:

QObject::connect(this, &HackClass::triggerWorkaround, targetAction_.data(), &QAction::trigger, Qt::QueuedConnection); 
emit triggerWorkaround(); 
QObject::disconnect(this, nullptr, targetAction_.data(), nullptr); 

しかし、それは混乱3行のコードです。これを行うには混乱のない方法がありますか?私はQMetaObject::invokeMethodを見つけましたが、率直に言って、私の現在のソリューションよりも10倍も混乱しています。また、私は文字列としてメソッド名を使用したくない!

+0

サーバーのイベントループ用に別のスレッドを作成することがあります。 – Velkan

答えて

2

あなたはこのように機能QueuedInvokeにそのを分離することができます:

//overload for methods/slots 
//the slot gets invoked in the thread where the QObject lives 
template <typename Object, typename T> 
void QueuedInvoke(Object* object, T (Object::* f)()){ 
    QObject signalSource; 
    QObject::connect(&signalSource, &QObject::destroyed, 
        object, f, Qt::QueuedConnection); 
} 
//overload for functors 
//the functor gets invoked in the thread where the contextObject lives 
//or in the current thread if no contextObject is provided 
template <typename Func> 
void QueuedInvoke(Func&& f, QObject* contextObject = QAbstractEventDispatcher::instance()){ 
    QObject signalSource; 
    QObject::connect(&signalSource, &QObject::destroyed, 
        contextObject, std::forward<Func>(f), Qt::QueuedConnection); 
} 

これはイベントループにキューに入れられたイベントを投稿する一時的なQObjectから放出されるdestroyed()信号を活用します。スロット/ファンクタは、イベントループがそのイベントを処理するときに実際に呼び出されます。与えられたQThreadでファンクタを実行についての私の答えは、this great answerに基づいて

QueuedInvoke(targetAction_.data(), &QAction::trigger); 

ので、代わりにあなたが投稿3行で、次のような上記の機能を使用することができます。詳細については、それを参照することができます。

+0

これは引数を持つメソッドでは機能しないと仮定しています... –

+0

@TomášZato、この制限を回避するためにラムダ式を使うことができます... – Mike

+0

@TomášZato、特定のスレッドでラムダを実行するには、コンテキスト 'QObject'を提供します。 – Mike

関連する問題