【发布时间】:2019-03-12 11:27:28
【问题描述】:
我打算创建一个工作线程,它将以 1 秒的间隔更新 QTWidget(将其视为数字时钟或进度条更新器可能是一个更好的类比给应用程序)。
我的应用程序是特定于航空电子设备的,它计算飞行路径上的飞行跟踪信息,并在飞行过程中以 1 秒的间隔定期更新地图或其他一些 QT 小部件(我想您可以将其视为一种进度bar - 在我的情况下,进度条可以被地图或表格小部件替换)。该线程可能需要大约 10-20 秒来计算整个飞行数据 - (但是它几乎可以立即获得第一个结果) - 这些结果需要以 1 秒的间隔发送到 GUI 以更新飞机的位置在地图上。
对于合并更新工作线程的计时器的正确和错误方法存在很多混淆。我发现的最好的知识来源是一个 QtCon talk entitied Multithreading with Qt - Giuseppe D’Angelo - 似乎首选的方法是让一个工人 QObject 不继承 QThread 并且让计时器在它自己的事件处理程序中运行 -但是关于将工作线程移动到另一个我不太了解的线程有很多困惑,我正在寻找一些关于如何正确执行此操作的规范建议。在 Lambda 中这样做是理想的,因为我可以保持逻辑和线程相对隔离,这将是理想的。
我正在寻找是否有人可以为我指出类似示例的方向(尤其是如果它使用现代 Lambdas)。我目前使用的是 QT 5.11.2。
我的worker对象(其中包含QTimer如下):
class SimulatedFlightWorker : public QObject
{
Q_OBJECT
public:
explicit SimulatedFlightWorker()
: mpMMRFlightData{}
{}
public slots:
// worker thread slot that computes the mpMMRFlightData
void importSimulatedFlight(
const QString& fileName,
const int aPlaybackSpeed);
void updateGUI(int secondsElapsed);
signals:
// every second during the flight we need to send a new MMR
// record to the GUI - to display on a spreadsheet or google map
void updateFlightData(const MMRTimedRecord& rMMRRecord);
// this is effectively when the worker thread is done
void flightCompleted();
private:
QTimer mTimer;
// the
std::unique_ptr<MMRFlightData> mpMMRFlightData;
};
这是我设置信号和插槽的代码(还没有工作)
// Experimental worker model adapted from YouTube tutorial
// by Giuseppe di Angelo https://www.youtube.com/watch?v=BgqT6SIeRn4
auto thread = new QThread;
auto worker = new SimulatedFlightWorker;
connect(thread, &QThread::started, worker, &SimulatedFlightWorker::importSimulatedFlight);
connect(worker, &SimulatedFlightWorker::flightCompleted, thread, &QThread::quit);
connect(thread, &QThread::finished, worker, &SimulatedFlightWorker::deleteLater);
worker->moveToThread(thread);
thread->start();
【问题讨论】:
-
为每个计时器滴答声创建一个新线程在性能方面可能是个坏主意,这意味着很多上下文切换,因此,您可以尝试以下方法:1.
QThreadPool和QRunnable, 2. 或QtConcurrent::run()doc.qt.io/qt-5/qtconcurrentrun.html,使用QFutureWatcher使future 真正异步并使用信号和槽doc.qt.io/qt-5/qfuturewatcher.html 分派结果。 future 方式是现代方式,因为它有点像 JavaScript 的 promises 和 Dart 的 futures,还要注意:任务将NOT被执行直到线程可用。跨度> -
@user9335240 我只想在 SimulatedFlightWorker 的后台运行 1 个 QTimer,它会发出超时信号,如下所示 connect(&mTimer, &QTimer::timeout, &this, &SimulatedFlightWorker ::更新飞行数据)。不太确定这种语法,但我猜我必须在我的工人的构造函数中的某个地方这样做
-
尝试使用
QtConcurrent::run([=](){ /* Execute your lambda here */ });这将返回一个QFuture,QFutureWatcher<int> watcher; connect(&watcher, SIGNAL(finished()), &myObject, SLOT(handleFinished())); // Start the computation. QFuture<int> future = QtConcurrent::run([=](){ /* Execute your lambda here */ }); watcher.setFuture(future);
标签: c++ multithreading qt qthread qtimer