2017-06-02 57 views
0

Qt GUI C++ 5.6.2でウィンドウ上にグラフィックをいくつか作成しているプロジェクトをしようとしています。 私は 'createVerticalSpeedIndicator'と 'createAirSpeedIndicator'という2つのメソッドを持っています。これらのメソッドはwhile(1)ループでグラフィックスを作成し、qApp-> processEvents()を使用する必要があります。それらのうちの1人が働いているときには完全にやっています。しかし、私はその両方を同時にかつ常に実行する必要があります。Qt複数の非同期WhileループとqApp-> processEvents();

私はそれらを同時に実行するために何ができるのですか?

ありがとうございました

+0

あなたは現在と同じで両方のインジケータを描画しようとしていますループ、または2つ? OpenGLウィジェットまたは組み込みウィジェットを使用していますか?別のスレッドを使用していますか?いくつかの擬似コードの例が良いでしょう。この記述を考えれば、間違っている可能性のあるものが多すぎます。 – rationalcoder

+0

私はスレッドを使用しましたが、私はグラフィックを作成しているので、私は同じループで私がsmotthを失う可能性があると思ったいくつかのstuckingsを見た。私はこの15グラフィックを多目的にします。私は組み込みのウ​​ィジェットを使用しています –

+0

どのような "stuckings"を経験しましたか?どの組み込みのウ​​ィジェットを使用していますか? 15、正確には?あなたのコードの一部とあなたのグラフィックの画像を投稿してください。 – rationalcoder

答えて

0

解決策は、コントロールフローを反転することです。 while() { ... processEvents() ... }は、非同期コードのパターンではありません。なぜなら、実際にはそうではないにも関わらず、制御の軌跡があると仮定しているからです。 processEventscreateXxxメソッドを再入力する可能性があるため、スタックを使い果たしていないことは幸いです。ここで

は、変換の完全な例です。その時点で

// Input 
void Class::createVerticalSpeedIndicator() { 
    for (int i = 0; i < 100; i ++) { 
    doStep(i); 
    QCoreApplication::processEvents(); 
    } 
} 
// Step 1 - factor out state 
void Class::createVerticalSpeedIndicator() { 
    int i = 0; 
    while (i < 100) { 
    doStep(i); 
    QCoreApplication::processEvents(); 
    i++; 
    } 
}; 
// Step 2 - convert to continuation form 
void Class::createVerticalSpeedIndicator() { 
    int i = 0; 
    auto continuation = [=]() mutable { 
    if (!(i < 100)) 
     return false; 
    doStep(i); 
    QCoreApplication::processEvents(); 
    i++; 
    return true; 
    }; 
    while (continuation()); 
}; 
// Step 3 - execute the continuation asynchronously 
auto Class::createVerticalSpeedIndicator() { 
    int i = 0; 
    return async(this, [=]() mutable { 
    if (!(i < 100)) 
     return false; 
    doStep(i); 
    i++; // note the removal of processEvents here 
    return true; 
    }); 
}; 

template <typename F> void async(QObject * parent, F && continuation) { 
    auto timer = new QTimer(parent); 
    timer->start(0); 
    connect(timer, &QTimer::timeout, [timer, c = std::move(continuation)]{ 
    if (!c()) 
     timer->deleteLater(); 
    }); 
} 

あなたはcreateAirSpeedIndicatorに同じ変換を適用して、それらを開始することができますあなたのクラスのコンストラクタ:両方のタスクは、主スレッド内で非同期的かつ擬似的に同時に実行される。すなわち、各タスクは、代替的に、単一のステップを実行する。別ウィンドウ(タブ)の大きな表示で見る

タスクを連鎖させたい、つまり、前のタスクが終了した後にタスクを開始するとします。ユーザーコードでの変更は単純なことができます:

Class::Class(QWidget * parent) : QWidget(parent) { 
    ... 
    createVerticalSpeedIndicator() 
    >> createAirSpeedIndicator() 
    >> someOtherTask(); 
} 

async機能は現在、このような接続を行うことを可能にするクラスを返す必要があります。

struct TaskTimer { 
    QTimer * timer; 
    TaskTimer & operator>>(const TaskTimer & next) { 
    next.timer->stop(); 
    connect(timer, &QObject::destroyed, next.timer, [timer = next.timer]{ 
     timer->start(0); 
    }); 
    timer = next.timer; 
    return *this; 
    } 
}; 

template <typename F> TaskTimer async(QObject * parent, F && continuation) { 
    TaskTimer task{new QTimer(parent)}; 
    task.timer->start(0); 
    connect(task.timer, &QTimer::timeout, 
      [timer = task.timer, c = std::move(continuation)]{ 
      if (!c()) 
       timer->deleteLater(); 
    }); 
    return task; 
} 
関連する問題