解決策は、コントロールフローを反転することです。 while() { ... processEvents() ... }
は、非同期コードのパターンではありません。なぜなら、実際にはそうではないにも関わらず、制御の軌跡があると仮定しているからです。 processEvents
がcreateXxx
メソッドを再入力する可能性があるため、スタックを使い果たしていないことは幸いです。ここで
は、変換の完全な例です。その時点で
// 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;
}
あなたは現在と同じで両方のインジケータを描画しようとしていますループ、または2つ? OpenGLウィジェットまたは組み込みウィジェットを使用していますか?別のスレッドを使用していますか?いくつかの擬似コードの例が良いでしょう。この記述を考えれば、間違っている可能性のあるものが多すぎます。 – rationalcoder
私はスレッドを使用しましたが、私はグラフィックを作成しているので、私は同じループで私がsmotthを失う可能性があると思ったいくつかのstuckingsを見た。私はこの15グラフィックを多目的にします。私は組み込みのウィジェットを使用しています –
どのような "stuckings"を経験しましたか?どの組み込みのウィジェットを使用していますか? 15、正確には?あなたのコードの一部とあなたのグラフィックの画像を投稿してください。 – rationalcoder