2017-07-17 26 views
0

私はC++ QT5 Widgetデスクトップアプリケーションを作成していますが、スタート/ストップボタンを押すと別のスレッドで時間のかかる操作MainWindow::performLengthyOperation(bool)を実行する必要があります。別のスレッドでQT MainWindowメソッドを実行する

この時間がかかる操作は、私のMainWindow.h/cppでかなり長いメソッドです。バックグラウンドIOアクティビティを停止する操作には約6秒かかり、開始には約2秒かかります。開始/停止ボタンが押されている間、UIは応答しません。基本的には、私のボタンクリックイベントに接続されたスロットでは、以下のロジックを実行する必要があります。私はfollowing article出くわしこれを実行する方法の例を探していたが、私はそれはそのUIにアクセスできるように何とか労働者にメインウィンドウを取得する必要がありますように私は私のシナリオにそれを適応問題を抱えています

void 
MainWindow::on_pushButtonStart_clicked(bool checked) 
{ 
    // temporarily disable the pushbutton 
    // until the lengthy operation completes 
    mUI->pushButtonStart->setEnabled(false); 

    if (checked) { 
     // Start the timer tick callback 
     mTickTimer.start(APP_TICK, this); 
     mUI->pushButtonStart->setText("starting..."); 

     // This method needs to somehow run in its own QT thread 
     // and when finished, call a slot in this MainWindow to 
     // re-enable the pushButtonStart and change the statusBar 
     // to indicate "runing..." 
     performLengthyOperation(true); 
     //mUI->pushButtonStart->setText("Stop") 
     //mUI->statusBar->setStyleSheet("color: blue"); 
     //mUI->statusBar->showMessage("runing..."); 
    } else { // Stop the protocol threads 
     // Stop the subsystem protocol tick timer 
     mTickTimer.stop(); 
     mUI->pushButtonStart->setText("stopping..."); 
     // This method needs to somehow run in its own QT thread 
     // and when finished, call a slot in this MainWindow to 
     // re-enable the pushButtonStart and change the statusBar 
     // to indicate "ready..." 
     performLengthyOperation(false); 
     // finally toggle the UI controls 
     //mUI->pushButtonStart->setText("Start") 
     //mUI->statusBar->setStyleSheet("color: blue"); 
     //mUI->statusBar->showMessage("ready..."); 
    } 
} 

ウィジェットなどとそれは少し過剰なようだ。

これらの時間を要する操作(パラメータとしてメインウィンドウを渡すこと)が可能なラムダ関数を非同期で実行する簡単な方法を理想的に探しています。それはQThreadsを使用し、オブジェクトをスレッドなどに移動する方が望ましいでしょう。しかし、QTフレームワークがこれが安全で可能なものかどうかを知るには十分ではありません。 std ::非同期とラムダを使用して

+0

ウィンドウを渡しても、その他のスレッドから操作することはできません。これらの操作をメインスレッドにマーシャリングする必要があります(ただし、Qtはシグナル/スロットでこれを行うことができます)。 – Steve

答えて

1

があなたのメイン・ウィンドウクラスのメンバーとしてstd::future<void> future;を追加します。コード付き

追加スロットOnLengthyOperationPerformed

mUI->pushButtonStart->setText("Stop") 
mUI->statusBar->setStyleSheet("color: blue"); 
mUI->statusBar->showMessage("runing..."); 
mUI->pushButtonStart->setEnabled(true); 

信号void LengthOperationPerformed();を追加し、メイン・ウィンドウコンストラクタのスロットとそれを接続します。メインスレッドからスロットを呼び出したいので、接続の5番目のパラメータとしてQt::QueuedConnectionを渡します。他のコールと

future = std::async(std::launch::async, [this] { 
    performLengthyOperation(true); 
    emit LengthOperationPerformed(); 
}); 

同じ:あなたが書くことができon_pushButtonStart_clicked方法で次に

。別のスロットとシグナルを追加するか、またはスロットにフラグを渡します。

長いアクションは別のスレッドで実行され、終了するとMainWindowは信号を受信して​​ボタンを再び有効にします。

+0

呼び出し先のスレッドをキックオフするには:: get() – johnco3

+0

誰もいません。あなたは将来価値が保存される必要はありません。 –

+0

ありがとう、コンストラクタのconnect(this、SIGNAL(LengthyMethodPerformed(const bool))、SLOT(updateStartStopButton(const QString&))、Qt :: QueuedConnection)の接続構文を使用して、 QCoreApplication :: sendEvent: "別のスレッドが所有するオブジェクトにイベントを送信できません。現在のスレッド34e6b60。(タイプ 'QSerialPort')のレシーバ 'がスレッド40c460で作成されました。 – johnco3

関連する問題