2016-04-01 11 views
0

私のメインスレッドは、バックグラウンドスレッド(ネットワークサービス)を呼び出すQtウィンドウを実行していて、最終的に応答を期待しています。 UI:次のようにバックグラウンドスレッドからメインUIスレッドのlambda/std :: functionを呼び出す

// runs in main (GUI) thread 
void QTServer::onButtonClick(){ 
    srv->request(msg, 
     [this] 
      (std::shared_ptr<message> msg){ 
       this->ui.txtResponse->setText("received a response" + msg.data()); 
      }); 
} 

ネットワークサービスは次のとおりです。

std::function<void(std::shared_ptr<message>)> delegate_; 

void NetworkService::request(message& msg,std::function<void(std::shared_ptr<message> msg)> fn) 
{ 
    // send the request to the socket and store the callback for later 
    // ... 
    this->delegate_ = fn; 
} 

void NetworkService::onResponseReceived(std::shared_ptr<message> responseMsg) 
{ 
    // is called from the background thread (service) 
    // Here I would like to call the lambda function that the service stored somewhere (currently as an std::func member) 

    // psuedo: call In Main Thread: delegate_(responseMsg); 
} 

そのしくみを教えてください。それは機能するのでしょうか?

私はあなたがmainthreadで関数を呼び出すためにQMetaObject::invokeMethod(this, "method", Qt::QueuedConnectionを使用できることを知っているので、私は次のことを試してみました:

void NetworkService::onResponseReceived(std::shared_ptr<message> responseMsg) 
{ 
    QMetaObject::invokeMethod(this, "runInMainThread", Qt::QueuedConnection, QGenericArgument(), Q_ARG(std::function<void(std::shared_ptr<message>)>, delegate_)); 
} 

にはどうすれば_delegateの引数として、ここでresponseMsgを渡すのですか?

void QTServer::runInMainThread(std::function<void(std::shared_ptr<message>)> f) { 
    f(); 
} 

「これらの引数で機能していません」というエラーを取り除くにはどうすればよいですか?

答えて

1

削除QGenericArgument() - 内部ヘルパークラスです。 また、Q_ARGを使用するか、void *としてデータを送信するために独自の型を登録する必要があります。

Q_ARG(void*, delegate_) 

第二の問題 - のstd :: shared_ptrの、そしてf() - - 私はあなたがしようとしている何のために推奨される方法を信じて引数なしで呼び出すので、デフォルト引数

+0

うーん、それは私が 'Q_ART(ボイド*、delegate_)' – netik

+0

パスアドレスQ_ARG(ボイド*、&delegate_)しようとした場合、その後、reinterpret_castは<*のボイド(STD :: shared_ptrのを)>を使用し、 "なしコンストラクタが利用できる" と言います – jonezq

-1

を追加fは一つの引数を取る関数でありますQTで実現するには、QThreadと組み合わせてシグナルとスロットを使用する方法があります。たとえば:

MyObject * myObject = new MyObject(); //your worker 
QThread * myThread = new QThread(); //your thread 
myObject->moveToThread(myThread); 

QObject::connect(myThread, SIGNAL(started()), myObject, SLOT(startWorking())); //when thread starts, invoke the working method 
QObject::connect(myObject, SIGNAL(stoppedWorking()), this, SLOT(stoppedWorking())); //when worker signals it finished, invoke slot in main 

QObject::connect(myObject, SIGNAL(stoppedWorking()), myThread, SLOT(quit())); //quit the thread when worker signals that it finished 
QObject::connect(myObject, SIGNAL(gproxyExiting()), gproxy, SLOT(deleteLater())); //cleanup 
QObject::connect(myThread, SIGNAL(finished()), myThread, SLOT(deleteLater())); //cleanup 

この方法で全体のライフサイクルは、あなたのために自動的に管理されており、メインスレッド上の労働者とスロット内部の信号が相互に通信するために何でも定義することができます。

関連する問題